diff --git a/.vscode/settings.json b/.vscode/settings.json index 3b664107..a1508387 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { - "git.ignoreLimitWarning": true + "git.ignoreLimitWarning": true, + "terminal.integrated.defaultProfile.windows": "Command Prompt" } \ No newline at end of file diff --git a/backend/.env b/InfoGenie-backend/.env similarity index 100% rename from backend/.env rename to InfoGenie-backend/.env diff --git a/backend/.env.production b/InfoGenie-backend/.env.production old mode 100755 new mode 100644 similarity index 100% rename from backend/.env.production rename to InfoGenie-backend/.env.production diff --git a/InfoGenie-backend/ai_config.json b/InfoGenie-backend/ai_config.json new file mode 100644 index 00000000..e2aea1aa --- /dev/null +++ b/InfoGenie-backend/ai_config.json @@ -0,0 +1,13 @@ +{ + "deepseek": { + "api_key": "sk-832f8e5250464de08a31523c7fd71295", + "api_base": "https://api.deepseek.com", + "model": ["deepseek-chat","deepseek-reasoner"] + }, + + "kimi": { + "api_key": "sk-zdg9NBpTlhOcDDpoWfaBKu0KNDdGv18SipORnL2utawja0bE", + "api_base": "https://api.moonshot.cn", + "model": ["kimi-k2-0905-preview","kimi-k2-0711-preview"] + } +} \ No newline at end of file diff --git a/backend/app.py b/InfoGenie-backend/app.py old mode 100755 new mode 100644 similarity index 97% rename from backend/app.py rename to InfoGenie-backend/app.py index 1975c060..bf3bfc54 --- a/backend/app.py +++ b/InfoGenie-backend/app.py @@ -18,6 +18,7 @@ import secrets from modules.auth import auth_bp from modules.user_management import user_bp from modules.email_service import init_mail +from modules.aimodelapp import aimodelapp_bp from config import Config @@ -41,6 +42,7 @@ def create_app(): # 注册蓝图 app.register_blueprint(auth_bp, url_prefix='/api/auth') app.register_blueprint(user_bp, url_prefix='/api/user') + app.register_blueprint(aimodelapp_bp, url_prefix='/api/aimodelapp') # 基础路由 @app.route('/') @@ -136,7 +138,7 @@ def create_app(): try: # 获取项目根目录 project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - ai_directory = os.path.join(project_root, 'frontend', 'aimodelapp') + ai_directory = os.path.join(project_root, 'frontend', 'public', 'aimodelapp') # 安全检查:确保文件路径在允许的目录内 full_path = os.path.join(ai_directory, filename) diff --git a/backend/config.py b/InfoGenie-backend/config.py old mode 100755 new mode 100644 similarity index 100% rename from backend/config.py rename to InfoGenie-backend/config.py diff --git a/InfoGenie-backend/modules/__pycache__/aimodelapp.cpython-313.pyc b/InfoGenie-backend/modules/__pycache__/aimodelapp.cpython-313.pyc new file mode 100644 index 00000000..a094e037 Binary files /dev/null and b/InfoGenie-backend/modules/__pycache__/aimodelapp.cpython-313.pyc differ diff --git a/backend/modules/__pycache__/api_60s.cpython-313.pyc b/InfoGenie-backend/modules/__pycache__/api_60s.cpython-313.pyc similarity index 100% rename from backend/modules/__pycache__/api_60s.cpython-313.pyc rename to InfoGenie-backend/modules/__pycache__/api_60s.cpython-313.pyc diff --git a/backend/modules/__pycache__/api_scanner.cpython-313.pyc b/InfoGenie-backend/modules/__pycache__/api_scanner.cpython-313.pyc similarity index 100% rename from backend/modules/__pycache__/api_scanner.cpython-313.pyc rename to InfoGenie-backend/modules/__pycache__/api_scanner.cpython-313.pyc diff --git a/backend/modules/__pycache__/auth.cpython-313.pyc b/InfoGenie-backend/modules/__pycache__/auth.cpython-313.pyc similarity index 88% rename from backend/modules/__pycache__/auth.cpython-313.pyc rename to InfoGenie-backend/modules/__pycache__/auth.cpython-313.pyc index 51dc2f2b..fa2731a8 100644 Binary files a/backend/modules/__pycache__/auth.cpython-313.pyc and b/InfoGenie-backend/modules/__pycache__/auth.cpython-313.pyc differ diff --git a/backend/modules/__pycache__/email_service.cpython-313.pyc b/InfoGenie-backend/modules/__pycache__/email_service.cpython-313.pyc similarity index 100% rename from backend/modules/__pycache__/email_service.cpython-313.pyc rename to InfoGenie-backend/modules/__pycache__/email_service.cpython-313.pyc diff --git a/backend/modules/__pycache__/smallgame.cpython-313.pyc b/InfoGenie-backend/modules/__pycache__/smallgame.cpython-313.pyc similarity index 100% rename from backend/modules/__pycache__/smallgame.cpython-313.pyc rename to InfoGenie-backend/modules/__pycache__/smallgame.cpython-313.pyc diff --git a/InfoGenie-backend/modules/__pycache__/user_management.cpython-313.pyc b/InfoGenie-backend/modules/__pycache__/user_management.cpython-313.pyc new file mode 100644 index 00000000..cb15a4fc Binary files /dev/null and b/InfoGenie-backend/modules/__pycache__/user_management.cpython-313.pyc differ diff --git a/InfoGenie-backend/modules/aimodelapp.py b/InfoGenie-backend/modules/aimodelapp.py new file mode 100644 index 00000000..72dedcbc --- /dev/null +++ b/InfoGenie-backend/modules/aimodelapp.py @@ -0,0 +1,765 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +AI模型应用服务模块 +Created by: 神奇万事通 +Date: 2025-01-15 +""" + +from flask import Blueprint, request, jsonify +import requests +import json +import os +from datetime import datetime + +# 创建蓝图 +aimodelapp_bp = Blueprint('aimodelapp', __name__) + +#加载AI配置文件 +def load_ai_config(): + """加载AI配置文件""" + try: + config_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'ai_config.json') + with open(config_path, 'r', encoding='utf-8') as f: + return json.load(f) + except Exception as e: + print(f"加载AI配置失败: {e}") + return None + +#调用DeepSeek API,带重试机制 +def call_deepseek_api(messages, model="deepseek-chat", max_retries=3): + """调用DeepSeek API,带重试机制""" + config = load_ai_config() + if not config or 'deepseek' not in config: + return None, "AI配置加载失败" + + deepseek_config = config['deepseek'] + + headers = { + 'Authorization': f'Bearer {deepseek_config["api_key"]}', + 'Content-Type': 'application/json' + } + + data = { + 'model': model, + 'messages': messages, + 'temperature': 0.7, + 'max_tokens': 2000 + } + + import time + + for attempt in range(max_retries): + try: + # 增加超时时间到90秒 + response = requests.post( + f"{deepseek_config['api_base']}/chat/completions", + headers=headers, + json=data, + timeout=90 + ) + + if response.status_code == 200: + result = response.json() + return result['choices'][0]['message']['content'], None + else: + error_msg = f"API调用失败: {response.status_code} - {response.text}" + if attempt < max_retries - 1: + print(f"第{attempt + 1}次尝试失败,等待重试: {error_msg}") + time.sleep(2 ** attempt) # 指数退避 + continue + return None, error_msg + + except requests.exceptions.Timeout: + error_msg = "API请求超时" + if attempt < max_retries - 1: + print(f"第{attempt + 1}次尝试超时,等待重试") + time.sleep(2 ** attempt) # 指数退避 + continue + return None, f"{error_msg}(已重试{max_retries}次)" + + except Exception as e: + error_msg = f"API调用异常: {str(e)}" + if attempt < max_retries - 1: + print(f"第{attempt + 1}次尝试异常,等待重试: {error_msg}") + time.sleep(2 ** attempt) # 指数退避 + continue + return None, f"{error_msg}(已重试{max_retries}次)" + +#调用Kimi API +def call_kimi_api(messages, model="kimi-k2-0905-preview"): + """调用Kimi API""" + config = load_ai_config() + if not config or 'kimi' not in config: + return None, "AI配置加载失败" + + kimi_config = config['kimi'] + + headers = { + 'Authorization': f'Bearer {kimi_config["api_key"]}', + 'Content-Type': 'application/json' + } + + data = { + 'model': model, + 'messages': messages, + 'temperature': 0.7, + 'max_tokens': 2000 + } + + try: + response = requests.post( + f"{kimi_config['api_base']}/v1/chat/completions", + headers=headers, + json=data, + timeout=30 + ) + + if response.status_code == 200: + result = response.json() + return result['choices'][0]['message']['content'], None + else: + return None, f"API调用失败: {response.status_code} - {response.text}" + + except Exception as e: + return None, f"API调用异常: {str(e)}" + +#统一的AI聊天接口 +@aimodelapp_bp.route('/chat', methods=['POST']) +def ai_chat(): + """统一的AI聊天接口""" + try: + data = request.get_json() + + if not data: + return jsonify({'error': '请求数据为空'}), 400 + + # 获取请求参数 + messages = data.get('messages', []) + model_provider = data.get('provider', 'deepseek') # 默认使用deepseek + model_name = data.get('model', 'deepseek-chat') # 默认模型 + + if not messages: + return jsonify({'error': '消息内容不能为空'}), 400 + + # 根据提供商调用对应的API + if model_provider == 'deepseek': + content, error = call_deepseek_api(messages, model_name) + elif model_provider == 'kimi': + content, error = call_kimi_api(messages, model_name) + else: + return jsonify({'error': f'不支持的AI提供商: {model_provider}'}), 400 + + if error: + return jsonify({'error': error}), 500 + + return jsonify({ + 'success': True, + 'content': content, + 'provider': model_provider, + 'model': model_name, + 'timestamp': datetime.now().isoformat() + }) + + except Exception as e: + return jsonify({'error': f'服务器错误: {str(e)}'}), 500 + +#姓名分析专用接口 +@aimodelapp_bp.route('/name-analysis', methods=['POST']) +def name_analysis(): + """姓名分析专用接口""" + try: + data = request.get_json() + name = data.get('name', '').strip() + + if not name: + return jsonify({'error': '姓名不能为空'}), 400 + + # 构建姓名分析的专业提示词 + prompt = f"""你是一位专业的姓名学专家和语言学家,请对输入的姓名进行全面分析。请直接输出分析结果,不要包含任何思考过程或标签。 + +姓名:{name} + +请按照以下格式严格输出分析结果: + +【稀有度评分】 +评分:X% +评价:[对稀有度的详细说明,包括姓氏和名字的常见程度分析] + +【音韵评价】 +评分:X% +评价:[对音韵美感的分析,包括声调搭配、读音流畅度、音律和谐度等] + +【含义解读】 +[详细分析姓名的寓意内涵,包括: +1. 姓氏的历史渊源和文化背景 +2. 名字各字的含义和象征 +3. 整体姓名的寓意组合 +4. 可能体现的父母期望或文化内涵 +5. 与传统文化、诗词典故的关联等] + +要求: +1. 评分必须是1-100的整数百分比,要有明显区分度,避免雷同 +2. 分析要专业、客观、有依据,评分要根据实际情况有所差异 +3. 含义解读要详细深入,至少150字 +4. 严格按照上述格式输出,不要添加思考过程、标签或其他内容 +5. 如果是生僻字或罕见姓名,要特别说明 +6. 直接输出最终结果,不要显示推理过程""" + + messages = [ + {"role": "user", "content": prompt} + ] + + # 使用DeepSeek进行分析 + content, error = call_deepseek_api(messages) + + if error: + return jsonify({'error': error}), 500 + + return jsonify({ + 'success': True, + 'analysis': content, + 'name': name, + 'timestamp': datetime.now().isoformat() + }) + + except Exception as e: + return jsonify({'error': f'姓名分析失败: {str(e)}'}), 500 + +#变量命名助手接口 +@aimodelapp_bp.route('/variable-naming', methods=['POST']) +def variable_naming(): + """变量命名助手接口""" + try: + data = request.get_json() + description = data.get('description', '').strip() + language = data.get('language', 'javascript').lower() + + if not description: + return jsonify({'error': '变量描述不能为空'}), 400 + + # 构建变量命名的提示词 + prompt = f"""你是一个专业的变量命名助手。请根据以下描述为变量生成合适的名称: + +描述:{description} + +请为每种命名规范生成3个变量名建议: +1. camelCase (驼峰命名法) +2. PascalCase (帕斯卡命名法) +3. snake_case (下划线命名法) +4. kebab-case (短横线命名法) +5. CONSTANT_CASE (常量命名法) + +要求: +- 变量名要准确反映功能和用途 +- 严格遵循各自的命名规范 +- 避免使用缩写,除非是广泛认知的缩写 +- 名称要简洁但具有描述性 +- 考虑代码的可读性和维护性 + +请按以下JSON格式返回: +{{ + "suggestions": {{ + "camelCase": [ + {{"name": "变量名1", "description": "解释说明1"}}, + {{"name": "变量名2", "description": "解释说明2"}}, + {{"name": "变量名3", "description": "解释说明3"}} + ], + "PascalCase": [ + {{"name": "变量名1", "description": "解释说明1"}}, + {{"name": "变量名2", "description": "解释说明2"}}, + {{"name": "变量名3", "description": "解释说明3"}} + ], + "snake_case": [ + {{"name": "变量名1", "description": "解释说明1"}}, + {{"name": "变量名2", "description": "解释说明2"}}, + {{"name": "变量名3", "description": "解释说明3"}} + ], + "kebab-case": [ + {{"name": "变量名1", "description": "解释说明1"}}, + {{"name": "变量名2", "description": "解释说明2"}}, + {{"name": "变量名3", "description": "解释说明3"}} + ], + "CONSTANT_CASE": [ + {{"name": "变量名1", "description": "解释说明1"}}, + {{"name": "变量名2", "description": "解释说明2"}}, + {{"name": "变量名3", "description": "解释说明3"}} + ] + }} +}} + +只返回JSON格式的结果,不要包含其他文字。""" + + messages = [ + {"role": "user", "content": prompt} + ] + + # 使用DeepSeek进行分析 + content, error = call_deepseek_api(messages) + + if error: + return jsonify({'error': error}), 500 + + # 解析AI返回的JSON格式数据 + try: + # 尝试直接解析JSON + ai_response = json.loads(content) + suggestions = ai_response.get('suggestions', {}) + except json.JSONDecodeError: + # 如果直接解析失败,尝试提取JSON部分 + import re + json_match = re.search(r'\{[\s\S]*\}', content) + if json_match: + try: + ai_response = json.loads(json_match.group()) + suggestions = ai_response.get('suggestions', {}) + except json.JSONDecodeError: + return jsonify({'error': 'AI返回的数据格式无法解析'}), 500 + else: + return jsonify({'error': 'AI返回的数据中未找到有效的JSON格式'}), 500 + + return jsonify({ + 'success': True, + 'suggestions': suggestions, + 'description': description, + 'language': language, + 'timestamp': datetime.now().isoformat() + }) + + except Exception as e: + return jsonify({'error': f'变量命名失败: {str(e)}'}), 500 + +@aimodelapp_bp.route('/poetry', methods=['POST']) +def poetry_assistant(): + """AI写诗助手接口""" + try: + data = request.get_json() + theme = data.get('theme', '').strip() + style = data.get('style', '现代诗').strip() + mood = data.get('mood', '').strip() + + if not theme: + return jsonify({'error': '诗歌主题不能为空'}), 400 + + # 构建写诗的提示词 + prompt = f"""你是一位才华横溢的诗人,请根据以下要求创作一首诗歌。 + +主题:{theme} +风格:{style} +情感基调:{mood if mood else '自由发挥'} + +创作要求: +1. 紧扣主题,情感真挚 +2. 语言优美,意境深远 +3. 符合指定的诗歌风格 +4. 长度适中,朗朗上口 +5. 如果是古体诗,注意平仄和韵律 + +请直接输出诗歌作品,不需要额外的解释或分析。""" + + messages = [ + {"role": "user", "content": prompt} + ] + + # 使用DeepSeek进行创作 + content, error = call_deepseek_api(messages) + + if error: + return jsonify({'error': error}), 500 + + return jsonify({ + 'success': True, + 'poem': content, + 'theme': theme, + 'style': style, + 'mood': mood, + 'timestamp': datetime.now().isoformat() + }) + + except Exception as e: + return jsonify({'error': f'诗歌创作失败: {str(e)}'}), 500 + +@aimodelapp_bp.route('/translation', methods=['POST']) +def translation(): + """AI语言翻译接口""" + try: + data = request.get_json() + source_text = data.get('source_text', '').strip() + target_language = data.get('target_language', 'zh-CN').strip() + + if not source_text: + return jsonify({'error': '翻译内容不能为空'}), 400 + + # 语言映射 + language_map = { + 'zh-CN': '中文(简体)', + 'zh-TW': '中文(繁体)', + 'en': '英语', + 'ja': '日语', + 'ko': '韩语', + 'fr': '法语', + 'de': '德语', + 'es': '西班牙语', + 'it': '意大利语', + 'pt': '葡萄牙语', + 'ru': '俄语', + 'ar': '阿拉伯语', + 'hi': '印地语', + 'th': '泰语', + 'vi': '越南语' + } + + target_language_name = language_map.get(target_language, target_language) + + # 构建翻译的专业提示词 + prompt = f"""你是一位专业的翻译专家,精通多种语言的翻译工作。请将以下文本翻译成{target_language_name}。 + +原文:{source_text} + +翻译要求: +1. 【信】- 忠实原文,准确传达原意,不遗漏、不添加、不歪曲 +2. 【达】- 译文通顺流畅,符合目标语言的表达习惯和语法规范 +3. 【雅】- 用词优美得体,风格与原文相符,具有良好的可读性 + +特别注意: +- 自动检测源语言,无需用户指定 +- 保持原文的语气、情感色彩和文体风格 +- 对于专业术语,提供准确的对应翻译 +- 对于文化特色词汇,在保持原意的基础上进行适当的本土化处理 +- 如果是单词或短语,提供多个常用含义的翻译 +- 如果是句子,确保语法正确、表达自然 + +请按以下JSON格式返回翻译结果: +{{ + "detected_language": "检测到的源语言名称", + "target_language": "{target_language_name}", + "translation": "翻译结果", + "alternative_translations": [ + "备选翻译1", + "备选翻译2", + "备选翻译3" + ], + "explanation": "翻译说明(包括语境、用法、注意事项等)", + "pronunciation": "目标语言的发音指导(如适用)" +}} + +只返回JSON格式的结果,不要包含其他文字。""" + + messages = [ + {"role": "user", "content": prompt} + ] + + # 使用DeepSeek进行翻译 + content, error = call_deepseek_api(messages) + + if error: + return jsonify({'error': error}), 500 + + return jsonify({ + 'success': True, + 'translation_result': content, + 'source_text': source_text, + 'target_language': target_language, + 'timestamp': datetime.now().isoformat() + }) + + except Exception as e: + return jsonify({'error': f'翻译失败: {str(e)}'}), 500 + +#现代文转文言文接口 +@aimodelapp_bp.route('/classical_conversion', methods=['POST']) +def classical_conversion(): + """现代文转文言文接口""" + try: + data = request.get_json() + modern_text = data.get('modern_text', '').strip() + style = data.get('style', '古雅').strip() + article_type = data.get('article_type', '散文').strip() + + if not modern_text: + return jsonify({'error': '现代文内容不能为空'}), 400 + + # 构建文言文转换的专业提示词 + prompt = f"""你是一位精通古代文言文的文学大师,擅长将现代文转换为优美的文言文。请将以下现代文转换为文言文。 + +现代文:{modern_text} + +转换要求: +1. 风格:{style} +2. 文体:{article_type} +3. 保持原文的核心意思和情感色彩 +4. 使用恰当的文言文语法和词汇 +5. 注重音韵美感和文字的雅致 +6. 根据不同风格调整用词和句式 + +风格说明: +- 古雅:典雅庄重,用词考究,句式工整 +- 简洁:言简意赅,删繁就简,朴实无华 +- 华丽:辞藻华美,对仗工整,音韵和谐 +- 朴实:平实自然,通俗易懂,贴近生活 + +文体特点: +- 散文:行文自由,情理并茂 +- 诗歌:讲究韵律,意境深远 +- 议论文:逻辑严密,论证有力 +- 记叙文:叙事生动,描写细腻 +- 书信:格式规范,情真意切 +- 公文:庄重严肃,用词准确 + +请按以下JSON格式返回转换结果: +{{ + "classical_text": "转换后的文言文", + "translation_notes": "转换说明,包括重要词汇的选择理由和语法特点", + "style_analysis": "风格分析,说明如何体现所选风格特点", + "difficulty_level": "难度等级(初级/中级/高级)", + "key_phrases": [ + {{ + "modern": "现代词汇", + "classical": "对应文言文词汇", + "explanation": "转换说明" + }} + ], + "cultural_elements": "文化内涵说明,包含的典故、意象等" +}} + +只返回JSON格式的结果,不要包含其他文字。""" + + messages = [ + {"role": "user", "content": prompt} + ] + + # 使用DeepSeek进行文言文转换 + content, error = call_deepseek_api(messages) + + if error: + return jsonify({'error': error}), 500 + + return jsonify({ + 'success': True, + 'conversion_result': content, + 'modern_text': modern_text, + 'style': style, + 'article_type': article_type, + 'timestamp': datetime.now().isoformat() + }) + + except Exception as e: + return jsonify({'error': f'文言文转换失败: {str(e)}'}), 500 + +#AI表情制作器接口 +@aimodelapp_bp.route('/expression-maker', methods=['POST']) +def expression_maker(): + """AI表情制作器接口""" + try: + data = request.get_json() + text = data.get('text', '').strip() + style = data.get('style', 'mixed').strip() + + if not text: + return jsonify({'error': '文字内容不能为空'}), 400 + + # 风格映射 + style_prompts = { + 'mixed': '混合使用Emoji表情和颜文字', + 'emoji': '仅使用Emoji表情符号', + 'kaomoji': '仅使用颜文字(日式表情符号)', + 'cute': '使用可爱风格的表情符号', + 'cool': '使用酷炫风格的表情符号' + } + + style_description = style_prompts.get(style, style_prompts['mixed']) + + # 构建表情制作的提示词 + prompt = f"""你是一个专业的表情符号专家,擅长为文字内容生成合适的表情符号。请根据以下文字内容生成相应的表情符号: + +文字内容:{text} +表情风格:{style_description} + +请为这个文字内容生成表情符号,要求: +1. 准确表达文字的情感和含义 +2. 符合指定的表情风格 +3. 提供多样化的选择 +4. 包含使用场景说明 + +请按以下分类生成表情符号: +1. Emoji表情(使用Unicode表情符号) +2. 颜文字(使用ASCII字符组成的表情) +3. 组合表情(多个符号组合使用) + +每个分类提供5个不同的表情选项,每个选项包含: +- 表情符号本身 +- 适用场景说明 +- 情感强度(轻微/中等/强烈) + +请按以下JSON格式返回: +{{ + "expressions": {{ + "emoji": [ + {{ + "symbol": "😊", + "description": "适用场景和情感说明", + "intensity": "中等", + "usage": "使用建议" + }} + ], + "kaomoji": [ + {{ + "symbol": "(^_^)", + "description": "适用场景和情感说明", + "intensity": "轻微", + "usage": "使用建议" + }} + ], + "combination": [ + {{ + "symbol": "🎉✨", + "description": "适用场景和情感说明", + "intensity": "强烈", + "usage": "使用建议" + }} + ] + }}, + "summary": {{ + "emotion_analysis": "对输入文字的情感分析", + "recommended_usage": "推荐的使用场景", + "style_notes": "风格特点说明" + }} +}} + +只返回JSON格式的结果,不要包含其他文字。""" + + messages = [ + {"role": "user", "content": prompt} + ] + + # 使用DeepSeek进行分析 + content, error = call_deepseek_api(messages) + + if error: + return jsonify({'error': error}), 500 + + # 解析AI返回的JSON格式数据 + try: + # 尝试直接解析JSON + ai_response = json.loads(content) + expressions = ai_response.get('expressions', {}) + summary = ai_response.get('summary', {}) + except json.JSONDecodeError: + # 如果直接解析失败,尝试提取JSON部分 + import re + json_match = re.search(r'\{[\s\S]*\}', content) + if json_match: + try: + ai_response = json.loads(json_match.group()) + expressions = ai_response.get('expressions', {}) + summary = ai_response.get('summary', {}) + except json.JSONDecodeError: + return jsonify({'error': 'AI返回的数据格式无法解析'}), 500 + else: + return jsonify({'error': 'AI返回的数据中未找到有效的JSON格式'}), 500 + + return jsonify({ + 'success': True, + 'expressions': expressions, + 'summary': summary, + 'text': text, + 'style': style, + 'timestamp': datetime.now().isoformat() + }) + + except Exception as e: + return jsonify({'error': f'表情制作失败: {str(e)}'}), 500 + +#Linux命令生成接口 +@aimodelapp_bp.route('/linux-command', methods=['POST']) +def linux_command_generator(): + """Linux命令生成接口""" + try: + data = request.get_json() + task_description = data.get('task_description', '').strip() + difficulty_level = data.get('difficulty_level', 'beginner').strip() + + if not task_description: + return jsonify({'error': '任务描述不能为空'}), 400 + + # 构建Linux命令生成的专业提示词 + prompt = f"""你是一位Linux系统专家,请根据用户的任务描述生成相应的Linux命令。 + +任务描述:{task_description} +用户水平:{difficulty_level} + +请为这个任务生成合适的Linux命令,要求: +1. 命令准确可用,符合Linux标准 +2. 根据用户水平提供适当的复杂度 +3. 提供多种实现方式(如果有的话) +4. 包含安全提示和注意事项 +5. 解释每个命令的作用和参数 + +用户水平说明: +- beginner(初学者):提供基础命令,详细解释 +- intermediate(中级):提供常用命令和选项 +- advanced(高级):提供高效命令和高级用法 + +请按以下JSON格式返回: +{{ + "commands": [ + {{ + "command": "具体的Linux命令", + "description": "命令的详细说明", + "safety_level": "safe/caution/dangerous", + "explanation": "命令各部分的解释", + "example_output": "预期的命令输出示例", + "alternatives": ["替代命令1", "替代命令2"] + }} + ], + "safety_warnings": ["安全提示1", "安全提示2"], + "prerequisites": ["前置条件1", "前置条件2"], + "related_concepts": ["相关概念1", "相关概念2"] +}} + +只返回JSON格式的结果,不要包含其他文字。""" + + messages = [ + {"role": "user", "content": prompt} + ] + + # 使用DeepSeek进行命令生成 + content, error = call_deepseek_api(messages) + + if error: + return jsonify({'error': error}), 500 + + return jsonify({ + 'success': True, + 'command_result': content, + 'task_description': task_description, + 'difficulty_level': difficulty_level, + 'timestamp': datetime.now().isoformat() + }) + + except Exception as e: + return jsonify({'error': f'Linux命令生成失败: {str(e)}'}), 500 + +#获取可用的AI模型列表 +@aimodelapp_bp.route('/models', methods=['GET']) +def get_available_models(): + """获取可用的AI模型列表""" + try: + config = load_ai_config() + if not config: + return jsonify({'error': 'AI配置加载失败'}), 500 + + models = {} + for provider, provider_config in config.items(): + if 'model' in provider_config: + models[provider] = provider_config['model'] + + return jsonify({ + 'success': True, + 'models': models, + 'default_provider': 'deepseek', + 'default_model': 'deepseek-chat' + }) + + except Exception as e: + return jsonify({'error': f'获取模型列表失败: {str(e)}'}), 500 \ No newline at end of file diff --git a/backend/modules/auth.py b/InfoGenie-backend/modules/auth.py old mode 100755 new mode 100644 similarity index 98% rename from backend/modules/auth.py rename to InfoGenie-backend/modules/auth.py index 96fd48d4..b7adb752 --- a/backend/modules/auth.py +++ b/InfoGenie-backend/modules/auth.py @@ -218,7 +218,15 @@ def register(): '注册时间': datetime.now().isoformat(), '最后登录': None, '登录次数': 0, - '用户状态': 'active' + '用户状态': 'active', + '等级': 0, + '经验': 0, + '萌芽币': 0, + '签到系统': { + '连续签到天数': 0, + '今日是否已签到': False, + '签到时间': '2025-01-01' + } } result = users_collection.insert_one(user_data) diff --git a/backend/modules/email_service.py b/InfoGenie-backend/modules/email_service.py old mode 100755 new mode 100644 similarity index 100% rename from backend/modules/email_service.py rename to InfoGenie-backend/modules/email_service.py diff --git a/InfoGenie-backend/modules/user_management.py b/InfoGenie-backend/modules/user_management.py new file mode 100644 index 00000000..97b70df6 --- /dev/null +++ b/InfoGenie-backend/modules/user_management.py @@ -0,0 +1,408 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +用户管理模块 +Created by: 神奇万事通 +Date: 2025-09-02 +""" + +from flask import Blueprint, request, jsonify, session, current_app +from datetime import datetime +from bson import ObjectId +import jwt +from functools import wraps + +user_bp = Blueprint('user', __name__) + +def verify_token(token): + """验证JWT token""" + try: + payload = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=['HS256']) + return {'success': True, 'data': payload} + except jwt.ExpiredSignatureError: + return {'success': False, 'message': 'Token已过期'} + except jwt.InvalidTokenError: + return {'success': False, 'message': 'Token无效'} + +def login_required(f): + """登录验证装饰器(支持JWT token和session)""" + @wraps(f) + def decorated_function(*args, **kwargs): + # 优先检查JWT token + token = request.headers.get('Authorization') + if token: + if token.startswith('Bearer '): + token = token[7:] + + result = verify_token(token) + if result['success']: + request.current_user = result['data'] + return f(*args, **kwargs) + + # 回退到session验证 + if not session.get('logged_in'): + return jsonify({ + 'success': False, + 'message': '请先登录' + }), 401 + return f(*args, **kwargs) + return decorated_function + +@user_bp.route('/profile', methods=['GET']) +@login_required +def get_profile(): + """获取用户资料""" + try: + user_id = session.get('user_id') + users_collection = current_app.mongo.db.userdata + + user = users_collection.find_one({'_id': ObjectId(user_id)}) + + if not user: + return jsonify({ + 'success': False, + 'message': '用户不存在' + }), 404 + + # 返回用户信息(不包含密码) + profile = { + 'account': user['账号'], + 'register_time': user.get('注册时间'), + 'last_login': user.get('最后登录'), + 'login_count': user.get('登录次数', 0), + 'status': user.get('用户状态', 'active') + } + + return jsonify({ + 'success': True, + 'data': profile + }), 200 + + except Exception as e: + return jsonify({ + 'success': False, + 'message': f'服务器错误: {str(e)}' + }), 500 + +@user_bp.route('/change-password', methods=['POST']) +@login_required +def change_password(): + """修改密码""" + try: + data = request.get_json() + old_password = data.get('old_password', '').strip() + new_password = data.get('new_password', '').strip() + + if not old_password or not new_password: + return jsonify({ + 'success': False, + 'message': '旧密码和新密码不能为空' + }), 400 + + if len(new_password) < 6 or len(new_password) > 20: + return jsonify({ + 'success': False, + 'message': '新密码长度必须在6-20位之间' + }), 400 + + user_id = session.get('user_id') + users_collection = current_app.mongo.db.userdata + + user = users_collection.find_one({'_id': ObjectId(user_id)}) + + if not user: + return jsonify({ + 'success': False, + 'message': '用户不存在' + }), 404 + + from werkzeug.security import check_password_hash, generate_password_hash + + # 验证旧密码 + if not check_password_hash(user['密码'], old_password): + return jsonify({ + 'success': False, + 'message': '原密码错误' + }), 401 + + # 更新密码 + new_password_hash = generate_password_hash(new_password) + + result = users_collection.update_one( + {'_id': ObjectId(user_id)}, + {'$set': {'密码': new_password_hash}} + ) + + if result.modified_count > 0: + return jsonify({ + 'success': True, + 'message': '密码修改成功' + }), 200 + else: + return jsonify({ + 'success': False, + 'message': '密码修改失败' + }), 500 + + except Exception as e: + return jsonify({ + 'success': False, + 'message': f'服务器错误: {str(e)}' + }), 500 + +@user_bp.route('/stats', methods=['GET']) +@login_required +def get_user_stats(): + """获取用户统计信息""" + try: + user_id = session.get('user_id') + + # 这里可以添加更多统计信息,比如API调用次数等 + stats = { + 'login_today': 1, # 今日登录次数 + 'api_calls_today': 0, # 今日API调用次数 + 'total_api_calls': 0, # 总API调用次数 + 'join_days': 1, # 加入天数 + 'last_activity': datetime.now().isoformat() + } + + return jsonify({ + 'success': True, + 'data': stats + }), 200 + + except Exception as e: + return jsonify({ + 'success': False, + 'message': f'服务器错误: {str(e)}' + }), 500 + +@user_bp.route('/game-data', methods=['GET']) +@login_required +def get_user_game_data(): + """获取用户游戏数据""" + try: + # 优先从JWT token获取用户ID + if hasattr(request, 'current_user'): + user_id = request.current_user['user_id'] + else: + user_id = session.get('user_id') + + users_collection = current_app.mongo.db.userdata + + user = users_collection.find_one({'_id': ObjectId(user_id)}) + + if not user: + return jsonify({ + 'success': False, + 'message': '用户不存在' + }), 404 + + # 返回用户游戏数据 + game_data = { + 'level': user.get('等级', 0), + 'experience': user.get('经验', 0), + 'coins': user.get('萌芽币', 0), + 'checkin_system': user.get('签到系统', { + '连续签到天数': 0, + '今日是否已签到': False, + '签到时间': '2025-01-01' + }) + } + + return jsonify({ + 'success': True, + 'data': game_data + }), 200 + + except Exception as e: + return jsonify({ + 'success': False, + 'message': f'服务器错误: {str(e)}' + }), 500 + +@user_bp.route('/checkin', methods=['POST']) +@login_required +def daily_checkin(): + """每日签到""" + try: + # 优先从JWT token获取用户ID + if hasattr(request, 'current_user'): + user_id = request.current_user['user_id'] + else: + user_id = session.get('user_id') + + users_collection = current_app.mongo.db.userdata + + user = users_collection.find_one({'_id': ObjectId(user_id)}) + + if not user: + return jsonify({ + 'success': False, + 'message': '用户不存在' + }), 404 + + # 获取当前日期 + today = datetime.now().strftime('%Y-%m-%d') + + # 获取签到系统数据 + checkin_system = user.get('签到系统', { + '连续签到天数': 0, + '今日是否已签到': False, + '签到时间': '2025-01-01' + }) + + # 检查今日是否已签到 + if checkin_system.get('今日是否已签到', False) and checkin_system.get('签到时间') == today: + return jsonify({ + 'success': False, + 'message': '今日已签到,请明天再来!' + }), 400 + + # 计算连续签到天数 + last_checkin_date = checkin_system.get('签到时间', '2025-01-01') + consecutive_days = checkin_system.get('连续签到天数', 0) + + # 检查是否连续签到 + if last_checkin_date: + try: + last_date = datetime.strptime(last_checkin_date, '%Y-%m-%d') + today_date = datetime.strptime(today, '%Y-%m-%d') + days_diff = (today_date - last_date).days + + if days_diff == 1: + # 连续签到 + consecutive_days += 1 + elif days_diff > 1: + # 断签,重新开始 + consecutive_days = 1 + else: + # 同一天,不应该发生 + consecutive_days = consecutive_days + except: + consecutive_days = 1 + else: + consecutive_days = 1 + + # 签到奖励 + coin_reward = 300 + exp_reward = 200 + + # 获取当前用户数据 + current_coins = user.get('萌芽币', 0) + current_exp = user.get('经验', 0) + current_level = user.get('等级', 0) + + # 计算新的经验和等级 + new_exp = current_exp + exp_reward + new_level = current_level + + # 等级升级逻辑:100 × 1.2^(等级) + while True: + exp_needed = int(100 * (1.2 ** new_level)) + if new_exp >= exp_needed: + new_exp -= exp_needed + new_level += 1 + else: + break + + # 更新用户数据 + update_data = { + '萌芽币': current_coins + coin_reward, + '经验': new_exp, + '等级': new_level, + '签到系统': { + '连续签到天数': consecutive_days, + '今日是否已签到': True, + '签到时间': today + } + } + + result = users_collection.update_one( + {'_id': ObjectId(user_id)}, + {'$set': update_data} + ) + + if result.modified_count > 0: + level_up = new_level > current_level + return jsonify({ + 'success': True, + 'message': '签到成功!', + 'data': { + 'coin_reward': coin_reward, + 'exp_reward': exp_reward, + 'consecutive_days': consecutive_days, + 'level_up': level_up, + 'new_level': new_level, + 'new_coins': current_coins + coin_reward, + 'new_exp': new_exp + } + }), 200 + else: + return jsonify({ + 'success': False, + 'message': '签到失败,请稍后重试' + }), 500 + + except Exception as e: + return jsonify({ + 'success': False, + 'message': f'服务器错误: {str(e)}' + }), 500 + +@user_bp.route('/delete', methods=['POST']) +@login_required +def delete_account(): + """删除账户""" + try: + data = request.get_json() + password = data.get('password', '').strip() + + if not password: + return jsonify({ + 'success': False, + 'message': '请输入密码确认删除' + }), 400 + + user_id = session.get('user_id') + users_collection = current_app.mongo.db.userdata + + user = users_collection.find_one({'_id': ObjectId(user_id)}) + + if not user: + return jsonify({ + 'success': False, + 'message': '用户不存在' + }), 404 + + from werkzeug.security import check_password_hash + + # 验证密码 + if not check_password_hash(user['密码'], password): + return jsonify({ + 'success': False, + 'message': '密码错误' + }), 401 + + # 删除用户 + result = users_collection.delete_one({'_id': ObjectId(user_id)}) + + if result.deleted_count > 0: + # 清除会话 + session.clear() + + return jsonify({ + 'success': True, + 'message': '账户已成功删除' + }), 200 + else: + return jsonify({ + 'success': False, + 'message': '删除失败' + }), 500 + + except Exception as e: + return jsonify({ + 'success': False, + 'message': f'服务器错误: {str(e)}' + }), 500 diff --git a/backend/requirements.txt b/InfoGenie-backend/requirements.txt old mode 100755 new mode 100644 similarity index 100% rename from backend/requirements.txt rename to InfoGenie-backend/requirements.txt diff --git a/InfoGenie-backend/start_backend.bat b/InfoGenie-backend/start_backend.bat new file mode 100644 index 00000000..ec8b3e13 --- /dev/null +++ b/InfoGenie-backend/start_backend.bat @@ -0,0 +1,2 @@ +@echo off +python app.py \ No newline at end of file diff --git a/InfoGenie-backend/start_backend.sh b/InfoGenie-backend/start_backend.sh new file mode 100644 index 00000000..cd71ab28 --- /dev/null +++ b/InfoGenie-backend/start_backend.sh @@ -0,0 +1,2 @@ +#!/bin/bash +python3 app.py diff --git a/backend/test/email_test.py b/InfoGenie-backend/test/email_test.py old mode 100755 new mode 100644 similarity index 100% rename from backend/test/email_test.py rename to InfoGenie-backend/test/email_test.py diff --git a/backend/test/mongo_test.py b/InfoGenie-backend/test/mongo_test.py old mode 100755 new mode 100644 similarity index 100% rename from backend/test/mongo_test.py rename to InfoGenie-backend/test/mongo_test.py diff --git a/backend/test/test_email.py b/InfoGenie-backend/test/test_email.py old mode 100755 new mode 100644 similarity index 100% rename from backend/test/test_email.py rename to InfoGenie-backend/test/test_email.py diff --git a/backend/test/test_email_fix.py b/InfoGenie-backend/test/test_email_fix.py old mode 100755 new mode 100644 similarity index 100% rename from backend/test/test_email_fix.py rename to InfoGenie-backend/test/test_email_fix.py diff --git a/backend/test/test_mongo.py b/InfoGenie-backend/test/test_mongo.py old mode 100755 new mode 100644 similarity index 100% rename from backend/test/test_mongo.py rename to InfoGenie-backend/test/test_mongo.py diff --git a/InfoGenie-backend/后端架构文档.md b/InfoGenie-backend/后端架构文档.md new file mode 100644 index 00000000..e69de29b diff --git a/InfoGenie-backend/用户数据模板.json b/InfoGenie-backend/用户数据模板.json new file mode 100644 index 00000000..5b2f2d07 --- /dev/null +++ b/InfoGenie-backend/用户数据模板.json @@ -0,0 +1,13 @@ +{ + "账号":"3205788256", + "邮箱":"3205788256@qq.com", + "密码":"0123456789", + "等级":0, + "经验":0, + "萌芽币":0, + "签到系统":{ + "连续签到天数":0, + "今日是否已签到":false, + "签到时间":"2025-01-01" + } +} \ No newline at end of file diff --git a/frontend/.env.production b/InfoGenie-frontend/.env.development old mode 100755 new mode 100644 similarity index 100% rename from frontend/.env.production rename to InfoGenie-frontend/.env.development diff --git a/frontend/.env.local b/InfoGenie-frontend/.env.local similarity index 100% rename from frontend/.env.local rename to InfoGenie-frontend/.env.local diff --git a/InfoGenie-frontend/.env.production b/InfoGenie-frontend/.env.production new file mode 100644 index 00000000..0c9ca94e --- /dev/null +++ b/InfoGenie-frontend/.env.production @@ -0,0 +1 @@ +REACT_APP_API_URL=http://127.0.0.1:5002 \ No newline at end of file diff --git a/build_frontend.bat b/InfoGenie-frontend/build_frontend.bat old mode 100755 new mode 100644 similarity index 50% rename from build_frontend.bat rename to InfoGenie-frontend/build_frontend.bat index 66bfcc0c..20b19b16 --- a/build_frontend.bat +++ b/InfoGenie-frontend/build_frontend.bat @@ -1,6 +1,4 @@ @echo off -cd /d "e:\Python\InfoGenie\frontend\react-app" npm run build - npx serve -s build pause \ No newline at end of file diff --git a/frontend/env.backup b/InfoGenie-frontend/env.backup similarity index 100% rename from frontend/env.backup rename to InfoGenie-frontend/env.backup diff --git a/frontend/package-lock.json b/InfoGenie-frontend/package-lock.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/package-lock.json rename to InfoGenie-frontend/package-lock.json diff --git a/frontend/package.json b/InfoGenie-frontend/package.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/package.json rename to InfoGenie-frontend/package.json diff --git a/frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/css/background.css b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/css/background.css rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/css/background.css diff --git a/frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/css/style.css b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/css/style.css rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/css/style.css diff --git a/frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/index.html b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/index.html rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/index.html diff --git a/frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/js/script.js b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/js/script.js rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/js/script.js diff --git a/frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/接口集合.json b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/接口集合.json rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/接口集合.json diff --git a/frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/返回接口.json b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/返回接口.json rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机JavaScript趣味题/返回接口.json diff --git a/frontend/public/60sapi/娱乐消遣/随机KFC文案/css/background.css b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机KFC文案/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机KFC文案/css/background.css rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机KFC文案/css/background.css diff --git a/frontend/public/60sapi/娱乐消遣/随机KFC文案/css/style.css b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机KFC文案/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机KFC文案/css/style.css rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机KFC文案/css/style.css diff --git a/frontend/public/60sapi/娱乐消遣/随机KFC文案/index.html b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机KFC文案/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机KFC文案/index.html rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机KFC文案/index.html diff --git a/frontend/public/60sapi/娱乐消遣/随机KFC文案/js/main.js b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机KFC文案/js/main.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机KFC文案/js/main.js rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机KFC文案/js/main.js diff --git a/frontend/public/60sapi/娱乐消遣/随机KFC文案/接口集合.json b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机KFC文案/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机KFC文案/接口集合.json rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机KFC文案/接口集合.json diff --git a/frontend/public/60sapi/娱乐消遣/随机KFC文案/返回接口.json b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机KFC文案/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机KFC文案/返回接口.json rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机KFC文案/返回接口.json diff --git a/frontend/public/60sapi/娱乐消遣/随机一言/css/background.css b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机一言/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机一言/css/background.css rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机一言/css/background.css diff --git a/frontend/public/60sapi/娱乐消遣/随机一言/css/style.css b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机一言/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机一言/css/style.css rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机一言/css/style.css diff --git a/frontend/public/60sapi/娱乐消遣/随机一言/index.html b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机一言/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机一言/index.html rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机一言/index.html diff --git a/frontend/public/60sapi/娱乐消遣/随机一言/js/script.js b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机一言/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机一言/js/script.js rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机一言/js/script.js diff --git a/frontend/public/60sapi/娱乐消遣/随机一言/接口集合.json b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机一言/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机一言/接口集合.json rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机一言/接口集合.json diff --git a/frontend/public/60sapi/娱乐消遣/随机一言/返回接口.json b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机一言/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机一言/返回接口.json rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机一言/返回接口.json diff --git a/frontend/public/60sapi/娱乐消遣/随机冷笑话/css/Untitled-1.html b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机冷笑话/css/Untitled-1.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机冷笑话/css/Untitled-1.html rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机冷笑话/css/Untitled-1.html diff --git a/frontend/public/60sapi/娱乐消遣/随机冷笑话/css/background.css b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机冷笑话/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机冷笑话/css/background.css rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机冷笑话/css/background.css diff --git a/frontend/public/60sapi/娱乐消遣/随机冷笑话/css/style.css b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机冷笑话/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机冷笑话/css/style.css rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机冷笑话/css/style.css diff --git a/frontend/public/60sapi/娱乐消遣/随机冷笑话/index.html b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机冷笑话/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机冷笑话/index.html rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机冷笑话/index.html diff --git a/frontend/public/60sapi/娱乐消遣/随机冷笑话/js/script.js b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机冷笑话/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机冷笑话/js/script.js rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机冷笑话/js/script.js diff --git a/frontend/public/60sapi/娱乐消遣/随机冷笑话/接口集合.json b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机冷笑话/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机冷笑话/接口集合.json rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机冷笑话/接口集合.json diff --git a/frontend/public/60sapi/娱乐消遣/随机冷笑话/返回接口.json b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机冷笑话/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机冷笑话/返回接口.json rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机冷笑话/返回接口.json diff --git a/frontend/public/60sapi/娱乐消遣/随机发病文学/css/background.css b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机发病文学/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机发病文学/css/background.css rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机发病文学/css/background.css diff --git a/frontend/public/60sapi/娱乐消遣/随机发病文学/css/style.css b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机发病文学/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机发病文学/css/style.css rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机发病文学/css/style.css diff --git a/frontend/public/60sapi/娱乐消遣/随机发病文学/index.html b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机发病文学/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机发病文学/index.html rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机发病文学/index.html diff --git a/frontend/public/60sapi/娱乐消遣/随机发病文学/js/script.js b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机发病文学/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机发病文学/js/script.js rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机发病文学/js/script.js diff --git a/frontend/public/60sapi/娱乐消遣/随机发病文学/接口集合.json b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机发病文学/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机发病文学/接口集合.json rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机发病文学/接口集合.json diff --git a/frontend/public/60sapi/娱乐消遣/随机发病文学/返回接口.json b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机发病文学/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机发病文学/返回接口.json rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机发病文学/返回接口.json diff --git a/frontend/public/60sapi/娱乐消遣/随机唱歌音频/css/style.css b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机唱歌音频/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机唱歌音频/css/style.css rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机唱歌音频/css/style.css diff --git a/frontend/public/60sapi/娱乐消遣/随机唱歌音频/index.html b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机唱歌音频/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机唱歌音频/index.html rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机唱歌音频/index.html diff --git a/frontend/public/60sapi/娱乐消遣/随机唱歌音频/js/script.js b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机唱歌音频/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机唱歌音频/js/script.js rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机唱歌音频/js/script.js diff --git a/frontend/public/60sapi/娱乐消遣/随机唱歌音频/接口集合.json b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机唱歌音频/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机唱歌音频/接口集合.json rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机唱歌音频/接口集合.json diff --git a/frontend/public/60sapi/娱乐消遣/随机唱歌音频/返回接口.json b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机唱歌音频/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机唱歌音频/返回接口.json rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机唱歌音频/返回接口.json diff --git a/frontend/public/60sapi/娱乐消遣/随机搞笑段子/css/background.css b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机搞笑段子/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机搞笑段子/css/background.css rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机搞笑段子/css/background.css diff --git a/frontend/public/60sapi/娱乐消遣/随机搞笑段子/css/style.css b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机搞笑段子/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机搞笑段子/css/style.css rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机搞笑段子/css/style.css diff --git a/frontend/public/60sapi/娱乐消遣/随机搞笑段子/index.html b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机搞笑段子/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机搞笑段子/index.html rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机搞笑段子/index.html diff --git a/frontend/public/60sapi/娱乐消遣/随机搞笑段子/js/script.js b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机搞笑段子/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机搞笑段子/js/script.js rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机搞笑段子/js/script.js diff --git a/frontend/public/60sapi/娱乐消遣/随机搞笑段子/接口集合.json b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机搞笑段子/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机搞笑段子/接口集合.json rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机搞笑段子/接口集合.json diff --git a/frontend/public/60sapi/娱乐消遣/随机搞笑段子/返回接口.json b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机搞笑段子/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机搞笑段子/返回接口.json rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机搞笑段子/返回接口.json diff --git a/frontend/public/60sapi/娱乐消遣/随机运势/css/background.css b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机运势/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机运势/css/background.css rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机运势/css/background.css diff --git a/frontend/public/60sapi/娱乐消遣/随机运势/css/style.css b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机运势/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机运势/css/style.css rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机运势/css/style.css diff --git a/frontend/public/60sapi/娱乐消遣/随机运势/index.html b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机运势/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机运势/index.html rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机运势/index.html diff --git a/frontend/public/60sapi/娱乐消遣/随机运势/js/script.js b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机运势/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机运势/js/script.js rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机运势/js/script.js diff --git a/frontend/public/60sapi/娱乐消遣/随机运势/接口集合.json b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机运势/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机运势/接口集合.json rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机运势/接口集合.json diff --git a/frontend/public/60sapi/娱乐消遣/随机运势/返回接口.json b/InfoGenie-frontend/public/60sapi/娱乐消遣/随机运势/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/娱乐消遣/随机运势/返回接口.json rename to InfoGenie-frontend/public/60sapi/娱乐消遣/随机运势/返回接口.json diff --git a/frontend/public/60sapi/实用功能/EpicGames免费游戏/css/style.css b/InfoGenie-frontend/public/60sapi/实用功能/EpicGames免费游戏/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/EpicGames免费游戏/css/style.css rename to InfoGenie-frontend/public/60sapi/实用功能/EpicGames免费游戏/css/style.css diff --git a/frontend/public/60sapi/实用功能/EpicGames免费游戏/index.html b/InfoGenie-frontend/public/60sapi/实用功能/EpicGames免费游戏/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/EpicGames免费游戏/index.html rename to InfoGenie-frontend/public/60sapi/实用功能/EpicGames免费游戏/index.html diff --git a/frontend/public/60sapi/实用功能/EpicGames免费游戏/js/script.js b/InfoGenie-frontend/public/60sapi/实用功能/EpicGames免费游戏/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/EpicGames免费游戏/js/script.js rename to InfoGenie-frontend/public/60sapi/实用功能/EpicGames免费游戏/js/script.js diff --git a/frontend/public/60sapi/实用功能/EpicGames免费游戏/接口集合.json b/InfoGenie-frontend/public/60sapi/实用功能/EpicGames免费游戏/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/EpicGames免费游戏/接口集合.json rename to InfoGenie-frontend/public/60sapi/实用功能/EpicGames免费游戏/接口集合.json diff --git a/frontend/public/60sapi/实用功能/EpicGames免费游戏/返回接口.json b/InfoGenie-frontend/public/60sapi/实用功能/EpicGames免费游戏/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/EpicGames免费游戏/返回接口.json rename to InfoGenie-frontend/public/60sapi/实用功能/EpicGames免费游戏/返回接口.json diff --git a/frontend/public/60sapi/实用功能/公网IP地址/css/background.css b/InfoGenie-frontend/public/60sapi/实用功能/公网IP地址/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/公网IP地址/css/background.css rename to InfoGenie-frontend/public/60sapi/实用功能/公网IP地址/css/background.css diff --git a/frontend/public/60sapi/实用功能/公网IP地址/css/style.css b/InfoGenie-frontend/public/60sapi/实用功能/公网IP地址/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/公网IP地址/css/style.css rename to InfoGenie-frontend/public/60sapi/实用功能/公网IP地址/css/style.css diff --git a/frontend/public/60sapi/实用功能/公网IP地址/index.html b/InfoGenie-frontend/public/60sapi/实用功能/公网IP地址/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/公网IP地址/index.html rename to InfoGenie-frontend/public/60sapi/实用功能/公网IP地址/index.html diff --git a/frontend/public/60sapi/实用功能/公网IP地址/js/script.js b/InfoGenie-frontend/public/60sapi/实用功能/公网IP地址/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/公网IP地址/js/script.js rename to InfoGenie-frontend/public/60sapi/实用功能/公网IP地址/js/script.js diff --git a/frontend/public/60sapi/实用功能/公网IP地址/接口集合.json b/InfoGenie-frontend/public/60sapi/实用功能/公网IP地址/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/公网IP地址/接口集合.json rename to InfoGenie-frontend/public/60sapi/实用功能/公网IP地址/接口集合.json diff --git a/frontend/public/60sapi/实用功能/公网IP地址/返回接口.json b/InfoGenie-frontend/public/60sapi/实用功能/公网IP地址/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/公网IP地址/返回接口.json rename to InfoGenie-frontend/public/60sapi/实用功能/公网IP地址/返回接口.json diff --git a/frontend/public/60sapi/实用功能/农历信息/css/background.css b/InfoGenie-frontend/public/60sapi/实用功能/农历信息/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/农历信息/css/background.css rename to InfoGenie-frontend/public/60sapi/实用功能/农历信息/css/background.css diff --git a/frontend/public/60sapi/实用功能/农历信息/css/style.css b/InfoGenie-frontend/public/60sapi/实用功能/农历信息/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/农历信息/css/style.css rename to InfoGenie-frontend/public/60sapi/实用功能/农历信息/css/style.css diff --git a/frontend/public/60sapi/实用功能/农历信息/index.html b/InfoGenie-frontend/public/60sapi/实用功能/农历信息/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/农历信息/index.html rename to InfoGenie-frontend/public/60sapi/实用功能/农历信息/index.html diff --git a/frontend/public/60sapi/实用功能/农历信息/js/script.js b/InfoGenie-frontend/public/60sapi/实用功能/农历信息/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/农历信息/js/script.js rename to InfoGenie-frontend/public/60sapi/实用功能/农历信息/js/script.js diff --git a/frontend/public/60sapi/实用功能/农历信息/接口集合.json b/InfoGenie-frontend/public/60sapi/实用功能/农历信息/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/农历信息/接口集合.json rename to InfoGenie-frontend/public/60sapi/实用功能/农历信息/接口集合.json diff --git a/frontend/public/60sapi/实用功能/农历信息/返回接口.json b/InfoGenie-frontend/public/60sapi/实用功能/农历信息/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/农历信息/返回接口.json rename to InfoGenie-frontend/public/60sapi/实用功能/农历信息/返回接口.json diff --git a/frontend/public/60sapi/实用功能/哈希解压压缩/css/style.css b/InfoGenie-frontend/public/60sapi/实用功能/哈希解压压缩/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/哈希解压压缩/css/style.css rename to InfoGenie-frontend/public/60sapi/实用功能/哈希解压压缩/css/style.css diff --git a/frontend/public/60sapi/实用功能/哈希解压压缩/index.html b/InfoGenie-frontend/public/60sapi/实用功能/哈希解压压缩/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/哈希解压压缩/index.html rename to InfoGenie-frontend/public/60sapi/实用功能/哈希解压压缩/index.html diff --git a/frontend/public/60sapi/实用功能/哈希解压压缩/js/script.js b/InfoGenie-frontend/public/60sapi/实用功能/哈希解压压缩/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/哈希解压压缩/js/script.js rename to InfoGenie-frontend/public/60sapi/实用功能/哈希解压压缩/js/script.js diff --git a/frontend/public/60sapi/实用功能/哈希解压压缩/接口集合.json b/InfoGenie-frontend/public/60sapi/实用功能/哈希解压压缩/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/哈希解压压缩/接口集合.json rename to InfoGenie-frontend/public/60sapi/实用功能/哈希解压压缩/接口集合.json diff --git a/frontend/public/60sapi/实用功能/哈希解压压缩/返回接口.json b/InfoGenie-frontend/public/60sapi/实用功能/哈希解压压缩/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/哈希解压压缩/返回接口.json rename to InfoGenie-frontend/public/60sapi/实用功能/哈希解压压缩/返回接口.json diff --git a/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/background.css b/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/background.css new file mode 100644 index 00000000..8cadc9c7 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/background.css @@ -0,0 +1,137 @@ +/* 背景样式文件 */ + +/* 页面主背景 */ +body { + background: linear-gradient(135deg, #e8f5e8 0%, #f0fdf4 25%, #dcfce7 50%, #f0fdf4 75%, #e8f5e8 100%); + background-size: 400% 400%; + animation: gradientShift 15s ease infinite; + background-attachment: fixed; +} + +/* 背景动画 */ +@keyframes gradientShift { + 0% { + background-position: 0% 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0% 50%; + } +} + +/* 容器背景 */ +.container { + background: rgba(255, 255, 255, 0.1); + backdrop-filter: blur(10px); + border-radius: 20px; + border: 1px solid rgba(255, 255, 255, 0.2); +} + +/* 翻译框背景 */ +.translate-box { + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(20px); + border: 1px solid rgba(116, 198, 157, 0.3); +} + +/* 输入框背景 */ +#input-text { + background: rgba(255, 255, 255, 0.9); +} + +#input-text:focus { + background: rgba(255, 255, 255, 1); +} + +/* 输出框背景 */ +.output-text { + background: #f8fffe; +} + +/* 按钮背景 */ +.translate-btn { + background: linear-gradient(135deg, #74c69d, #52b788); +} + +.translate-btn:hover { + background: linear-gradient(135deg, #52b788, #40916c); +} + +.translate-btn:disabled { + background: #b7e4c7; +} + +.swap-btn { + background: #74c69d; +} + +.swap-btn:hover { + background: #52b788; +} + +/* 语言选择器背景 */ +.lang-select { + background: white; +} + +.lang-select:focus { + background: rgba(255, 255, 255, 1); +} + +/* 发音信息背景 */ +.pronounce-item { + background: rgba(116, 198, 157, 0.1); +} + +/* 清除和复制按钮背景 */ +.clear-btn:hover, +.copy-btn:hover { + background: rgba(116, 198, 157, 0.1); +} + +/* 提示消息背景 */ +.toast { + background: #52b788; +} + +.toast.error { + background: #e74c3c; +} + +/* 响应式背景调整 */ +@media (max-width: 767px) { + body { + background-size: 200% 200%; + animation-duration: 10s; + } + + .container { + background: rgba(255, 255, 255, 0.05); + backdrop-filter: blur(5px); + } + + .translate-box { + background: rgba(255, 255, 255, 0.98); + backdrop-filter: blur(15px); + } +} + +@media (max-width: 480px) { + body { + background-size: 150% 150%; + animation-duration: 8s; + } + + .container { + background: transparent; + backdrop-filter: none; + border: none; + } + + .translate-box { + background: rgba(255, 255, 255, 0.99); + backdrop-filter: blur(10px); + } +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/index.html b/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/index.html new file mode 100644 index 00000000..d32953c9 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/index.html @@ -0,0 +1,99 @@ + + + + + + 在线翻译 - 支持109种语言 + + + + +
+
+

在线机器翻译

+

支持109种语言互译

+
+ +
+
+
+
+ + +
+ + + +
+ + +
+
+ +
+
+
+ + +
+ +
+ 0/5000 +
+
+ +
+
+ + +
+
翻译结果将显示在这里...
+
+
+
+
+
+
+ +
+ +
+
+
+ +
+

数据来源于有道翻译,与其网页端同步

+
+
+ +
+ + + + \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/script.js b/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/script.js new file mode 100644 index 00000000..c0a5f087 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/script.js @@ -0,0 +1,452 @@ +// 全局变量 +let supportedLanguages = {}; +let isTranslating = false; + +// DOM元素 +const elements = { + fromLang: null, + toLang: null, + inputText: null, + outputText: null, + translateBtn: null, + swapBtn: null, + clearBtn: null, + copyBtn: null, + charCount: null, + detectedLang: null, + targetLang: null, + pronounceSection: null +}; + +// 初始化 +document.addEventListener('DOMContentLoaded', function() { + initializeElements(); + loadSupportedLanguages(); + bindEvents(); + updateCharCount(); +}); + +// 初始化DOM元素 +function initializeElements() { + elements.fromLang = document.getElementById('from-lang'); + elements.toLang = document.getElementById('to-lang'); + elements.inputText = document.getElementById('input-text'); + elements.outputText = document.getElementById('output-text'); + elements.translateBtn = document.getElementById('translate-btn'); + elements.swapBtn = document.getElementById('swap-btn'); + elements.clearBtn = document.getElementById('clear-btn'); + elements.copyBtn = document.getElementById('copy-btn'); + elements.charCount = document.getElementById('char-count'); + elements.detectedLang = document.getElementById('detected-lang'); + elements.targetLang = document.getElementById('target-lang'); + elements.pronounceSection = document.getElementById('pronounce-section'); +} + +// 加载支持的语言列表 +async function loadSupportedLanguages() { + try { + const response = await fetch('https://60s.viki.moe/v2/fanyi/langs'); + const data = await response.json(); + + if (data.code === 200 && data.data && Array.isArray(data.data)) { + // 转换数组格式为对象格式 + supportedLanguages = {}; + supportedLanguages['auto'] = '自动检测'; + data.data.forEach(lang => { + supportedLanguages[lang.code] = lang.label; + }); + populateLanguageSelectors(); + } else { + throw new Error('获取语言列表失败'); + } + } catch (error) { + console.error('加载语言列表失败:', error); + showToast('加载语言列表失败,请刷新页面重试', 'error'); + // 使用默认语言列表 + useDefaultLanguages(); + } +} + +// 使用默认语言列表(备用方案) +function useDefaultLanguages() { + supportedLanguages = { + 'auto': '自动检测', + 'zh-CHS': '中文', + 'en': '英语', + 'ja': '日语', + 'ko': '韩语', + 'fr': '法语', + 'de': '德语', + 'es': '西班牙语', + 'ru': '俄语', + 'th': '泰语', + 'ar': '阿拉伯语', + 'pt': '葡萄牙语', + 'it': '意大利语' + }; + populateLanguageSelectors(); +} + +// 填充语言选择器 +function populateLanguageSelectors() { + const fromSelect = elements.fromLang; + const toSelect = elements.toLang; + + // 清空现有选项 + fromSelect.innerHTML = ''; + toSelect.innerHTML = ''; + + // 添加语言选项 + Object.entries(supportedLanguages).forEach(([code, name]) => { + const fromOption = new Option(name, code); + const toOption = new Option(name, code); + + fromSelect.appendChild(fromOption); + toSelect.appendChild(toOption); + }); + + // 设置默认值 + fromSelect.value = 'auto'; + toSelect.value = 'en'; + + // 如果没有auto选项,则设置为中文 + if (!supportedLanguages['auto']) { + fromSelect.value = 'zh-CHS'; + } +} + +// 绑定事件 +function bindEvents() { + // 输入框事件 + elements.inputText.addEventListener('input', function() { + updateCharCount(); + clearOutput(); + }); + + elements.inputText.addEventListener('keydown', function(e) { + if (e.ctrlKey && e.key === 'Enter') { + translateText(); + } + }); + + // 按钮事件 + elements.translateBtn.addEventListener('click', translateText); + elements.swapBtn.addEventListener('click', swapLanguages); + elements.clearBtn.addEventListener('click', clearInput); + elements.copyBtn.addEventListener('click', copyOutput); + + // 语言选择器事件 + elements.fromLang.addEventListener('change', function() { + clearOutput(); + updateLanguageLabels(); + }); + + elements.toLang.addEventListener('change', function() { + clearOutput(); + updateLanguageLabels(); + }); +} + +// 更新字符计数 +function updateCharCount() { + const text = elements.inputText.value; + const count = text.length; + elements.charCount.textContent = `${count}/5000`; + + if (count > 5000) { + elements.charCount.style.color = '#e74c3c'; + } else { + elements.charCount.style.color = '#74c69d'; + } +} + +// 更新语言标签 +function updateLanguageLabels() { + const fromLang = elements.fromLang.value; + const toLang = elements.toLang.value; + + elements.detectedLang.textContent = supportedLanguages[fromLang] || '未知语言'; + elements.targetLang.textContent = supportedLanguages[toLang] || '未知语言'; +} + +// 翻译文本 +async function translateText() { + const text = elements.inputText.value.trim(); + + if (!text) { + showToast('请输入要翻译的文本', 'error'); + return; + } + + if (text.length > 5000) { + showToast('文本长度不能超过5000字符', 'error'); + return; + } + + if (isTranslating) { + return; + } + + setTranslating(true); + + try { + const fromLang = elements.fromLang.value; + const toLang = elements.toLang.value; + + // 构建请求URL + const params = new URLSearchParams({ + text: text, + from: fromLang, + to: toLang + }); + + const response = await fetch(`https://60s.viki.moe/v2/fanyi?${params}`); + const data = await response.json(); + + if (data.code === 200 && data.data) { + displayTranslationResult(data.data); + } else { + throw new Error(data.msg || '翻译失败'); + } + } catch (error) { + console.error('翻译失败:', error); + showToast('翻译失败: ' + error.message, 'error'); + elements.outputText.textContent = '翻译失败,请重试'; + } finally { + setTranslating(false); + } +} + +// 显示翻译结果 +function displayTranslationResult(data) { + // 显示翻译结果 + const translation = data.target ? data.target.text : ''; + elements.outputText.textContent = translation; + + // 更新检测到的语言 + if (data.source && data.source.type_desc) { + elements.detectedLang.textContent = `检测: ${data.source.type_desc}`; + } + + // 显示发音信息 + displayPronunciation(data); + + // 如果翻译结果为空 + if (!translation) { + elements.outputText.textContent = '未获取到翻译结果'; + } +} + +// 显示发音信息 +function displayPronunciation(data) { + const pronounceSection = elements.pronounceSection; + if (!pronounceSection) { + return; + } + pronounceSection.innerHTML = ''; + + // 原文发音 + if (data.source && data.source.pronounce) { + const sourcePhoneticDiv = document.createElement('div'); + sourcePhoneticDiv.className = 'pronounce-item show'; + sourcePhoneticDiv.textContent = `原文发音: [${data.source.pronounce}]`; + pronounceSection.appendChild(sourcePhoneticDiv); + } + + // 译文发音 + if (data.target && data.target.pronounce) { + const targetPhoneticDiv = document.createElement('div'); + targetPhoneticDiv.className = 'pronounce-item show'; + targetPhoneticDiv.textContent = `译文发音: [${data.target.pronounce}]`; + pronounceSection.appendChild(targetPhoneticDiv); + } +} + +// 设置翻译状态 +function setTranslating(translating) { + isTranslating = translating; + elements.translateBtn.disabled = translating; + + if (translating) { + elements.translateBtn.classList.add('loading'); + } else { + elements.translateBtn.classList.remove('loading'); + } +} + +// 交换语言 +function swapLanguages() { + const fromValue = elements.fromLang.value; + const toValue = elements.toLang.value; + + // 不能交换自动检测 + if (fromValue === 'auto') { + showToast('自动检测语言无法交换', 'error'); + return; + } + + elements.fromLang.value = toValue; + elements.toLang.value = fromValue; + + // 交换文本内容 + const inputText = elements.inputText.value; + const outputText = elements.outputText.textContent; + + if (outputText && outputText !== '翻译结果将在这里显示...' && outputText !== '翻译失败,请重试' && outputText !== '未获取到翻译结果') { + elements.inputText.value = outputText; + elements.outputText.textContent = inputText; + } + + updateCharCount(); + updateLanguageLabels(); + clearPronunciation(); +} + +// 清空输入 +function clearInput() { + elements.inputText.value = ''; + updateCharCount(); + clearOutput(); +} + +// 清空输出 +function clearOutput() { + elements.outputText.textContent = '翻译结果将在这里显示...'; + clearPronunciation(); +} + +// 清空发音信息 +function clearPronunciation() { + if (elements.pronounceSection) { + elements.pronounceSection.innerHTML = ''; + } +} + +// 复制输出 +function copyOutput() { + const text = elements.outputText.textContent; + + if (!text || text === '翻译结果将在这里显示...' || text === '翻译失败,请重试' || text === '未获取到翻译结果') { + showToast('没有可复制的内容', 'error'); + return; + } + + // 使用现代API复制 + if (navigator.clipboard) { + navigator.clipboard.writeText(text).then(() => { + showToast('已复制到剪贴板'); + }).catch(() => { + fallbackCopy(text); + }); + } else { + fallbackCopy(text); + } +} + +// 备用复制方法 +function fallbackCopy(text) { + const textArea = document.createElement('textarea'); + textArea.value = text; + textArea.style.position = 'fixed'; + textArea.style.opacity = '0'; + document.body.appendChild(textArea); + textArea.select(); + + try { + document.execCommand('copy'); + showToast('已复制到剪贴板'); + } catch (err) { + showToast('复制失败,请手动复制', 'error'); + } + + document.body.removeChild(textArea); +} + +// 显示提示消息 +function showToast(message, type = 'success') { + // 移除现有的toast + const existingToast = document.querySelector('.toast'); + if (existingToast) { + existingToast.remove(); + } + + const toast = document.createElement('div'); + toast.className = `toast ${type}`; + toast.textContent = message; + + document.body.appendChild(toast); + + // 显示toast + setTimeout(() => { + toast.classList.add('show'); + }, 100); + + // 自动隐藏 + setTimeout(() => { + toast.classList.remove('show'); + setTimeout(() => { + if (toast.parentNode) { + toast.parentNode.removeChild(toast); + } + }, 300); + }, 3000); +} + +// 工具函数:防抖 +function debounce(func, wait) { + let timeout; + return function executedFunction(...args) { + const later = () => { + clearTimeout(timeout); + func(...args); + }; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; +} + +// 添加键盘快捷键支持 +document.addEventListener('keydown', function(e) { + // Ctrl+Enter 翻译 + if (e.ctrlKey && e.key === 'Enter') { + e.preventDefault(); + translateText(); + } + + // Ctrl+Shift+C 复制结果 + if (e.ctrlKey && e.shiftKey && e.key === 'C') { + e.preventDefault(); + copyOutput(); + } + + // Ctrl+Shift+X 清空输入 + if (e.ctrlKey && e.shiftKey && e.key === 'X') { + e.preventDefault(); + clearInput(); + } + + // Ctrl+Shift+S 交换语言 + if (e.ctrlKey && e.shiftKey && e.key === 'S') { + e.preventDefault(); + swapLanguages(); + } +}); + +// 页面可见性变化时的处理 +document.addEventListener('visibilitychange', function() { + if (document.hidden) { + // 页面隐藏时暂停翻译请求 + if (isTranslating) { + setTranslating(false); + } + } +}); + +// 错误处理 +window.addEventListener('error', function(e) { + console.error('页面错误:', e.error); +}); + +window.addEventListener('unhandledrejection', function(e) { + console.error('未处理的Promise拒绝:', e.reason); +}); \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/styles.css b/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/styles.css new file mode 100644 index 00000000..099b81a9 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/styles.css @@ -0,0 +1,441 @@ +/* 基础样式重置 */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; + line-height: 1.6; + color: #2d5a3d; + min-height: 100vh; +} + +.container { + max-width: 1200px; + margin: 0 auto; + padding: 20px; + min-height: 100vh; + display: flex; + flex-direction: column; +} + +/* 头部样式 */ +.header { + text-align: center; + margin-bottom: 30px; +} + +.header h1 { + font-size: 2.5rem; + color: #1a4d2e; + margin-bottom: 10px; + font-weight: 700; +} + +.subtitle { + font-size: 1.1rem; + color: #4a7c59; + opacity: 0.9; +} + +/* 主要内容区域 */ +.main-content { + flex: 1; + display: flex; + justify-content: center; + align-items: flex-start; +} + +.translate-box { + width: 100%; + max-width: 900px; + border-radius: 20px; + padding: 30px; + box-shadow: 0 10px 30px rgba(26, 77, 46, 0.1); +} + +/* 语言选择器 */ +.language-selector { + display: flex; + align-items: center; + gap: 20px; + margin-bottom: 25px; + justify-content: center; +} + +.lang-group { + display: flex; + flex-direction: column; + gap: 8px; + flex: 1; + max-width: 200px; +} + +.lang-group label { + font-size: 0.9rem; + color: #2d5a3d; + font-weight: 500; +} + +.lang-select { + padding: 12px 16px; + border: 2px solid #74c69d; + border-radius: 12px; + color: #2d5a3d; + font-size: 1rem; + cursor: pointer; + transition: all 0.3s ease; +} + +.lang-select:focus { + outline: none; + border-color: #52b788; + box-shadow: 0 0 0 3px rgba(116, 198, 157, 0.2); +} + +.lang-select:hover { + border-color: #52b788; +} + +.swap-btn { + border: none; + border-radius: 50%; + width: 45px; + height: 45px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: all 0.3s ease; + color: white; + margin-top: 25px; +} + +.swap-btn:hover { + transform: rotate(180deg); +} + +/* 文本区域 */ +.text-areas { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 20px; + margin-bottom: 25px; +} + +.input-section, +.output-section { + display: flex; + flex-direction: column; +} + +.textarea-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; + padding: 0 5px; +} + +.detected-lang, +.target-lang { + font-size: 0.9rem; + color: #4a7c59; + font-weight: 500; +} + +.clear-btn, +.copy-btn { + background: none; + border: none; + color: #74c69d; + cursor: pointer; + padding: 5px; + border-radius: 6px; + transition: all 0.3s ease; +} + +.clear-btn:hover, +.copy-btn:hover { + color: #52b788; +} + +#input-text { + width: 100%; + height: 200px; + padding: 16px; + border: 2px solid #74c69d; + border-radius: 12px; + font-size: 1rem; + color: #2d5a3d; + resize: vertical; + transition: all 0.3s ease; + font-family: inherit; +} + +#input-text:focus { + outline: none; + border-color: #52b788; + box-shadow: 0 0 0 3px rgba(116, 198, 157, 0.2); +} + +#input-text::placeholder { + color: #74c69d; + opacity: 0.7; +} + +.output-text { + width: 100%; + height: 200px; + padding: 16px; + border: 2px solid #b7e4c7; + border-radius: 12px; + font-size: 1rem; + color: #2d5a3d; + overflow-y: auto; + line-height: 1.6; +} + +.char-count { + text-align: right; + font-size: 0.8rem; + color: #74c69d; + margin-top: 5px; +} + +.pronounce-section { + margin-top: 10px; + display: flex; + flex-direction: column; + gap: 5px; +} + +.pronounce-item { + font-size: 0.9rem; + color: #4a7c59; + font-style: italic; + padding: 5px 10px; + border-radius: 8px; + display: none; +} + +.pronounce-item.show { + display: block; +} + +/* 操作按钮 */ +.action-buttons { + display: flex; + justify-content: center; +} + +.translate-btn { + color: white; + border: none; + padding: 15px 40px; + border-radius: 25px; + font-size: 1.1rem; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + position: relative; + overflow: hidden; + min-width: 120px; + display: flex; + align-items: center; + justify-content: center; + gap: 10px; +} + +.translate-btn:hover { + transform: translateY(-2px); + box-shadow: 0 8px 20px rgba(116, 198, 157, 0.3); +} + +.translate-btn:active { + transform: translateY(0); +} + +.translate-btn:disabled { + cursor: not-allowed; + transform: none; + box-shadow: none; +} + +.loading-spinner { + width: 20px; + height: 20px; + border: 2px solid rgba(255, 255, 255, 0.3); + border-top: 2px solid white; + border-radius: 50%; + animation: spin 1s linear infinite; + display: none; +} + +.translate-btn.loading .btn-text { + display: none; +} + +.translate-btn.loading .loading-spinner { + display: block; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* 页脚 */ +.footer { + text-align: center; + margin-top: 30px; + padding: 20px; + color: #4a7c59; + font-size: 0.9rem; + opacity: 0.8; +} + +/* 提示消息 */ +.toast { + position: fixed; + top: 20px; + right: 20px; + color: white; + padding: 12px 20px; + border-radius: 8px; + font-size: 0.9rem; + transform: translateX(100%); + transition: transform 0.3s ease; + z-index: 1000; + box-shadow: 0 4px 12px rgba(82, 183, 136, 0.3); +} + +.toast.show { + transform: translateX(0); +} + +.toast.error { + box-shadow: 0 4px 12px rgba(231, 76, 60, 0.3); +} + +/* 平板适配 (768px - 1024px) */ +@media (max-width: 1024px) and (min-width: 768px) { + .container { + padding: 15px; + } + + .header h1 { + font-size: 2.2rem; + } + + .translate-box { + padding: 25px; + } + + .language-selector { + gap: 15px; + } + + .text-areas { + gap: 15px; + } + + #input-text, + .output-text { + height: 180px; + } +} + +/* 手机端适配 (最大768px) */ +@media (max-width: 767px) { + .container { + padding: 10px; + } + + .header h1 { + font-size: 1.8rem; + } + + .subtitle { + font-size: 1rem; + } + + .translate-box { + padding: 20px 15px; + border-radius: 15px; + } + + .language-selector { + flex-direction: column; + gap: 15px; + align-items: stretch; + } + + .lang-group { + max-width: none; + } + + .swap-btn { + align-self: center; + margin-top: 0; + order: 2; + } + + .text-areas { + grid-template-columns: 1fr; + gap: 20px; + } + + #input-text, + .output-text { + height: 150px; + font-size: 0.95rem; + } + + .translate-btn { + padding: 12px 30px; + font-size: 1rem; + width: 100%; + max-width: 200px; + } + + .toast { + right: 10px; + left: 10px; + transform: translateY(-100%); + } + + .toast.show { + transform: translateY(0); + } +} + +/* 超小屏幕适配 (最大480px) */ +@media (max-width: 480px) { + .header h1 { + font-size: 1.6rem; + } + + .translate-box { + padding: 15px 10px; + } + + .lang-select { + padding: 10px 12px; + font-size: 0.9rem; + } + + #input-text, + .output-text { + height: 120px; + padding: 12px; + font-size: 0.9rem; + } + + .translate-btn { + padding: 10px 25px; + font-size: 0.95rem; + } +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/在线翻译支持语言列表接口.json b/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/在线翻译支持语言列表接口.json new file mode 100644 index 00000000..5f4f0f2b --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/在线翻译支持语言列表接口.json @@ -0,0 +1,551 @@ +{ + "code": 200, + "message": "获取成功。数据来自官方/权威源头,以确保稳定与实时。开源地址 https://github.com/vikiboss/60s,反馈群 595941841", + "data": [ + { + "code": "sq", + "label": "阿尔巴尼亚语", + "alphabet": "A" + }, + { + "code": "ga", + "label": "爱尔兰语", + "alphabet": "A" + }, + { + "code": "et", + "label": "爱沙尼亚语", + "alphabet": "A" + }, + { + "code": "ar", + "label": "阿拉伯语", + "alphabet": "A" + }, + { + "code": "am", + "label": "阿姆哈拉语", + "alphabet": "A" + }, + { + "code": "az", + "label": "阿塞拜疆语", + "alphabet": "A" + }, + { + "code": "be", + "label": "白俄罗斯语", + "alphabet": "B" + }, + { + "code": "bg", + "label": "保加利亚语", + "alphabet": "B" + }, + { + "code": "eu", + "label": "巴斯克语", + "alphabet": "B" + }, + { + "code": "is", + "label": "冰岛语", + "alphabet": "B" + }, + { + "code": "pl", + "label": "波兰语", + "alphabet": "B" + }, + { + "code": "bs-Latn", + "label": "波斯尼亚语(拉丁语)", + "alphabet": "B" + }, + { + "code": "fa", + "label": "波斯语", + "alphabet": "B" + }, + { + "code": "da", + "label": "丹麦语", + "alphabet": "D" + }, + { + "code": "de", + "label": "德语", + "alphabet": "D" + }, + { + "code": "ru", + "label": "俄语", + "alphabet": "E" + }, + { + "code": "fr", + "label": "法语", + "alphabet": "F" + }, + { + "code": "tl", + "label": "菲律宾语", + "alphabet": "F" + }, + { + "code": "fi", + "label": "芬兰语", + "alphabet": "F" + }, + { + "code": "fy", + "label": "弗里斯兰语", + "alphabet": "F" + }, + { + "code": "km", + "label": "高棉语", + "alphabet": "G" + }, + { + "code": "ka", + "label": "格鲁吉亚语", + "alphabet": "G" + }, + { + "code": "gu", + "label": "古吉拉特语", + "alphabet": "G" + }, + { + "code": "ko", + "label": "韩语", + "alphabet": "H" + }, + { + "code": "ht", + "label": "海地语", + "alphabet": "H" + }, + { + "code": "ha", + "label": "豪萨语", + "alphabet": "H" + }, + { + "code": "kk", + "label": "哈萨克语", + "alphabet": "H" + }, + { + "code": "nl", + "label": "荷兰语", + "alphabet": "H" + }, + { + "code": "gl", + "label": "加利西亚语", + "alphabet": "J" + }, + { + "code": "ca", + "label": "加泰罗尼亚语", + "alphabet": "J" + }, + { + "code": "cs", + "label": "捷克语", + "alphabet": "J" + }, + { + "code": "ky", + "label": "吉尔吉斯斯坦语", + "alphabet": "J" + }, + { + "code": "kn", + "label": "卡纳达语", + "alphabet": "K" + }, + { + "code": "tlh", + "label": "克林贡语", + "alphabet": "K" + }, + { + "code": "hr", + "label": "克罗地亚语", + "alphabet": "K" + }, + { + "code": "otq", + "label": "克洛塔罗乙巳语", + "alphabet": "K" + }, + { + "code": "co", + "label": "科西嘉语", + "alphabet": "K" + }, + { + "code": "ku", + "label": "库尔德语", + "alphabet": "K" + }, + { + "code": "la", + "label": "拉丁语", + "alphabet": "L" + }, + { + "code": "lo", + "label": "老挝语", + "alphabet": "L" + }, + { + "code": "lv", + "label": "拉脱维亚语", + "alphabet": "L" + }, + { + "code": "lt", + "label": "立陶宛语", + "alphabet": "L" + }, + { + "code": "ro", + "label": "罗马尼亚语", + "alphabet": "L" + }, + { + "code": "lb", + "label": "卢森堡语", + "alphabet": "L" + }, + { + "code": "mg", + "label": "马尔加什语", + "alphabet": "M" + }, + { + "code": "mt", + "label": "马耳他语", + "alphabet": "M" + }, + { + "code": "mr", + "label": "马拉地语", + "alphabet": "M" + }, + { + "code": "ms", + "label": "马来语", + "alphabet": "M" + }, + { + "code": "ml", + "label": "马拉雅拉姆语", + "alphabet": "M" + }, + { + "code": "mi", + "label": "毛利语", + "alphabet": "M" + }, + { + "code": "mk", + "label": "马其顿语", + "alphabet": "M" + }, + { + "code": "mn", + "label": "蒙古语", + "alphabet": "M" + }, + { + "code": "bn", + "label": "孟加拉语", + "alphabet": "M" + }, + { + "code": "my", + "label": "缅甸语", + "alphabet": "M" + }, + { + "code": "mww", + "label": "苗族昂山土语", + "alphabet": "M" + }, + { + "code": "hmn", + "label": "苗族语", + "alphabet": "M" + }, + { + "code": "xh", + "label": "南非科萨语", + "alphabet": "N" + }, + { + "code": "zu", + "label": "南非祖鲁语", + "alphabet": "N" + }, + { + "code": "ne", + "label": "尼泊尔语", + "alphabet": "N" + }, + { + "code": "no", + "label": "挪威语", + "alphabet": "N" + }, + { + "code": "pa", + "label": "旁遮普语", + "alphabet": "P" + }, + { + "code": "ps", + "label": "普什图语", + "alphabet": "P" + }, + { + "code": "pt", + "label": "葡萄牙语", + "alphabet": "P" + }, + { + "code": "ny", + "label": "齐切瓦语", + "alphabet": "Q" + }, + { + "code": "ja", + "label": "日语", + "alphabet": "R" + }, + { + "code": "sv", + "label": "瑞典语", + "alphabet": "R" + }, + { + "code": "sr-Latn", + "label": "塞尔维亚语(拉丁语)", + "alphabet": "S" + }, + { + "code": "sr-Cyrl", + "label": "塞尔维亚语(西里尔)", + "alphabet": "S" + }, + { + "code": "st", + "label": "塞索托语", + "alphabet": "S" + }, + { + "code": "sm", + "label": "萨摩亚语", + "alphabet": "S" + }, + { + "code": "si", + "label": "僧伽罗语", + "alphabet": "S" + }, + { + "code": "eo", + "label": "世界语", + "alphabet": "S" + }, + { + "code": "sk", + "label": "斯洛伐克语", + "alphabet": "S" + }, + { + "code": "sl", + "label": "斯洛语尼亚语", + "alphabet": "S" + }, + { + "code": "sw", + "label": "斯瓦希里语", + "alphabet": "S" + }, + { + "code": "gd", + "label": "苏格兰盖尔语", + "alphabet": "S" + }, + { + "code": "so", + "label": "索马里语", + "alphabet": "S" + }, + { + "code": "ceb", + "label": "宿务语", + "alphabet": "S" + }, + { + "code": "te", + "label": "泰卢固语", + "alphabet": "T" + }, + { + "code": "ta", + "label": "泰米尔语", + "alphabet": "T" + }, + { + "code": "th", + "label": "泰语", + "alphabet": "T" + }, + { + "code": "tg", + "label": "塔吉克语", + "alphabet": "T" + }, + { + "code": "tr", + "label": "土耳其语", + "alphabet": "T" + }, + { + "code": "cy", + "label": "威尔士语", + "alphabet": "W" + }, + { + "code": "zh-lzh", + "label": "文言文", + "alphabet": "W" + }, + { + "code": "ur", + "label": "乌尔都语", + "alphabet": "W" + }, + { + "code": "uk", + "label": "乌克兰语", + "alphabet": "W" + }, + { + "code": "uz", + "label": "乌兹别克语", + "alphabet": "W" + }, + { + "code": "haw", + "label": "夏威夷语", + "alphabet": "X" + }, + { + "code": "es", + "label": "西班牙语", + "alphabet": "X" + }, + { + "code": "he", + "label": "希伯来语", + "alphabet": "X" + }, + { + "code": "el", + "label": "希腊语", + "alphabet": "X" + }, + { + "code": "sd", + "label": "信德语", + "alphabet": "X" + }, + { + "code": "hu", + "label": "匈牙利语", + "alphabet": "X" + }, + { + "code": "sn", + "label": "修纳语", + "alphabet": "X" + }, + { + "code": "en", + "label": "英语", + "alphabet": "Y" + }, + { + "code": "hy", + "label": "亚美尼亚语", + "alphabet": "Y" + }, + { + "code": "ig", + "label": "伊博语", + "alphabet": "Y" + }, + { + "code": "it", + "label": "意大利语", + "alphabet": "Y" + }, + { + "code": "yi", + "label": "意第绪语", + "alphabet": "Y" + }, + { + "code": "hi", + "label": "印地语", + "alphabet": "Y" + }, + { + "code": "id", + "label": "印度尼西亚语", + "alphabet": "Y" + }, + { + "code": "su", + "label": "印尼巽他语", + "alphabet": "Y" + }, + { + "code": "jw", + "label": "印尼爪哇语", + "alphabet": "Y" + }, + { + "code": "yua", + "label": "尤卡坦玛雅语", + "alphabet": "Y" + }, + { + "code": "yo", + "label": "约鲁巴语", + "alphabet": "Y" + }, + { + "code": "vi", + "label": "越南语", + "alphabet": "Y" + }, + { + "code": "zh-CHS", + "label": "中文", + "alphabet": "Z" + }, + { + "code": "zh-CHT", + "label": "中文(繁体)", + "alphabet": "Z" + } + ] +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/返回接口.json b/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/返回接口.json new file mode 100644 index 00000000..cc373914 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/实用功能/在线翻译/返回接口.json @@ -0,0 +1 @@ +{"code":200,"message":"所有数据均来自官方,确保稳定与实时,用户群: 595941841,开源地址: https://github.com/vikiboss/60s","data":{"source":{"text":"こんにちは","type":"ja","type_desc":"日语","pronounce":"Konnitiha"},"target":{"text":"你好","type":"zh-CHS","type_desc":"中文","pronounce":"nĭhăo"}}} \ No newline at end of file diff --git a/frontend/public/60sapi/实用功能/天气预报/css/background.css b/InfoGenie-frontend/public/60sapi/实用功能/天气预报/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/天气预报/css/background.css rename to InfoGenie-frontend/public/60sapi/实用功能/天气预报/css/background.css diff --git a/frontend/public/60sapi/实用功能/天气预报/css/style.css b/InfoGenie-frontend/public/60sapi/实用功能/天气预报/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/天气预报/css/style.css rename to InfoGenie-frontend/public/60sapi/实用功能/天气预报/css/style.css diff --git a/frontend/public/60sapi/实用功能/天气预报/index.html b/InfoGenie-frontend/public/60sapi/实用功能/天气预报/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/天气预报/index.html rename to InfoGenie-frontend/public/60sapi/实用功能/天气预报/index.html diff --git a/frontend/public/60sapi/实用功能/天气预报/js/script.js b/InfoGenie-frontend/public/60sapi/实用功能/天气预报/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/天气预报/js/script.js rename to InfoGenie-frontend/public/60sapi/实用功能/天气预报/js/script.js diff --git a/frontend/public/60sapi/实用功能/天气预报/接口集合.json b/InfoGenie-frontend/public/60sapi/实用功能/天气预报/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/天气预报/接口集合.json rename to InfoGenie-frontend/public/60sapi/实用功能/天气预报/接口集合.json diff --git a/frontend/public/60sapi/实用功能/天气预报/返回接口.json b/InfoGenie-frontend/public/60sapi/实用功能/天气预报/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/天气预报/返回接口.json rename to InfoGenie-frontend/public/60sapi/实用功能/天气预报/返回接口.json diff --git a/frontend/public/60sapi/实用功能/实时天气[目前有问题]/background.css b/InfoGenie-frontend/public/60sapi/实用功能/实时天气[目前有问题]/background.css similarity index 100% rename from frontend/public/60sapi/实用功能/实时天气[目前有问题]/background.css rename to InfoGenie-frontend/public/60sapi/实用功能/实时天气[目前有问题]/background.css diff --git a/frontend/public/60sapi/实用功能/实时天气[目前有问题]/index.html b/InfoGenie-frontend/public/60sapi/实用功能/实时天气[目前有问题]/index.html similarity index 100% rename from frontend/public/60sapi/实用功能/实时天气[目前有问题]/index.html rename to InfoGenie-frontend/public/60sapi/实用功能/实时天气[目前有问题]/index.html diff --git a/frontend/public/60sapi/实用功能/实时天气[目前有问题]/script.js b/InfoGenie-frontend/public/60sapi/实用功能/实时天气[目前有问题]/script.js similarity index 100% rename from frontend/public/60sapi/实用功能/实时天气[目前有问题]/script.js rename to InfoGenie-frontend/public/60sapi/实用功能/实时天气[目前有问题]/script.js diff --git a/frontend/public/60sapi/实用功能/实时天气[目前有问题]/styles.css b/InfoGenie-frontend/public/60sapi/实用功能/实时天气[目前有问题]/styles.css similarity index 100% rename from frontend/public/60sapi/实用功能/实时天气[目前有问题]/styles.css rename to InfoGenie-frontend/public/60sapi/实用功能/实时天气[目前有问题]/styles.css diff --git a/frontend/public/60sapi/实用功能/实时天气[目前有问题]/返回接口.json b/InfoGenie-frontend/public/60sapi/实用功能/实时天气[目前有问题]/返回接口.json similarity index 100% rename from frontend/public/60sapi/实用功能/实时天气[目前有问题]/返回接口.json rename to InfoGenie-frontend/public/60sapi/实用功能/实时天气[目前有问题]/返回接口.json diff --git a/frontend/public/60sapi/实用功能/密码强度检测/css/style.css b/InfoGenie-frontend/public/60sapi/实用功能/密码强度检测/css/style.css similarity index 100% rename from frontend/public/60sapi/实用功能/密码强度检测/css/style.css rename to InfoGenie-frontend/public/60sapi/实用功能/密码强度检测/css/style.css diff --git a/frontend/public/60sapi/实用功能/密码强度检测/index.html b/InfoGenie-frontend/public/60sapi/实用功能/密码强度检测/index.html similarity index 100% rename from frontend/public/60sapi/实用功能/密码强度检测/index.html rename to InfoGenie-frontend/public/60sapi/实用功能/密码强度检测/index.html diff --git a/frontend/public/60sapi/实用功能/密码强度检测/js/script.js b/InfoGenie-frontend/public/60sapi/实用功能/密码强度检测/js/script.js similarity index 100% rename from frontend/public/60sapi/实用功能/密码强度检测/js/script.js rename to InfoGenie-frontend/public/60sapi/实用功能/密码强度检测/js/script.js diff --git a/frontend/public/60sapi/实用功能/密码强度检测/返回接口.json b/InfoGenie-frontend/public/60sapi/实用功能/密码强度检测/返回接口.json similarity index 100% rename from frontend/public/60sapi/实用功能/密码强度检测/返回接口.json rename to InfoGenie-frontend/public/60sapi/实用功能/密码强度检测/返回接口.json diff --git a/frontend/public/60sapi/实用功能/生成二维码/css/background.css b/InfoGenie-frontend/public/60sapi/实用功能/生成二维码/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/生成二维码/css/background.css rename to InfoGenie-frontend/public/60sapi/实用功能/生成二维码/css/background.css diff --git a/frontend/public/60sapi/实用功能/生成二维码/css/style.css b/InfoGenie-frontend/public/60sapi/实用功能/生成二维码/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/生成二维码/css/style.css rename to InfoGenie-frontend/public/60sapi/实用功能/生成二维码/css/style.css diff --git a/frontend/public/60sapi/实用功能/生成二维码/index.html b/InfoGenie-frontend/public/60sapi/实用功能/生成二维码/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/生成二维码/index.html rename to InfoGenie-frontend/public/60sapi/实用功能/生成二维码/index.html diff --git a/frontend/public/60sapi/实用功能/生成二维码/js/script.js b/InfoGenie-frontend/public/60sapi/实用功能/生成二维码/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/生成二维码/js/script.js rename to InfoGenie-frontend/public/60sapi/实用功能/生成二维码/js/script.js diff --git a/frontend/public/60sapi/实用功能/生成二维码/接口集合.json b/InfoGenie-frontend/public/60sapi/实用功能/生成二维码/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/生成二维码/接口集合.json rename to InfoGenie-frontend/public/60sapi/实用功能/生成二维码/接口集合.json diff --git a/frontend/public/60sapi/实用功能/百度百科词条/css/background.css b/InfoGenie-frontend/public/60sapi/实用功能/百度百科词条/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/百度百科词条/css/background.css rename to InfoGenie-frontend/public/60sapi/实用功能/百度百科词条/css/background.css diff --git a/frontend/public/60sapi/实用功能/百度百科词条/css/style.css b/InfoGenie-frontend/public/60sapi/实用功能/百度百科词条/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/百度百科词条/css/style.css rename to InfoGenie-frontend/public/60sapi/实用功能/百度百科词条/css/style.css diff --git a/frontend/public/60sapi/实用功能/百度百科词条/index.html b/InfoGenie-frontend/public/60sapi/实用功能/百度百科词条/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/百度百科词条/index.html rename to InfoGenie-frontend/public/60sapi/实用功能/百度百科词条/index.html diff --git a/frontend/public/60sapi/实用功能/百度百科词条/js/script.js b/InfoGenie-frontend/public/60sapi/实用功能/百度百科词条/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/百度百科词条/js/script.js rename to InfoGenie-frontend/public/60sapi/实用功能/百度百科词条/js/script.js diff --git a/frontend/public/60sapi/实用功能/百度百科词条/接口集合.json b/InfoGenie-frontend/public/60sapi/实用功能/百度百科词条/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/百度百科词条/接口集合.json rename to InfoGenie-frontend/public/60sapi/实用功能/百度百科词条/接口集合.json diff --git a/frontend/public/60sapi/实用功能/百度百科词条/返回接口.json b/InfoGenie-frontend/public/60sapi/实用功能/百度百科词条/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/百度百科词条/返回接口.json rename to InfoGenie-frontend/public/60sapi/实用功能/百度百科词条/返回接口.json diff --git a/frontend/public/60sapi/实用功能/身体健康分析/background.css b/InfoGenie-frontend/public/60sapi/实用功能/身体健康分析/background.css similarity index 100% rename from frontend/public/60sapi/实用功能/身体健康分析/background.css rename to InfoGenie-frontend/public/60sapi/实用功能/身体健康分析/background.css diff --git a/frontend/public/60sapi/实用功能/身体健康分析/index.html b/InfoGenie-frontend/public/60sapi/实用功能/身体健康分析/index.html similarity index 100% rename from frontend/public/60sapi/实用功能/身体健康分析/index.html rename to InfoGenie-frontend/public/60sapi/实用功能/身体健康分析/index.html diff --git a/frontend/public/60sapi/实用功能/身体健康分析/script.js b/InfoGenie-frontend/public/60sapi/实用功能/身体健康分析/script.js similarity index 100% rename from frontend/public/60sapi/实用功能/身体健康分析/script.js rename to InfoGenie-frontend/public/60sapi/实用功能/身体健康分析/script.js diff --git a/frontend/public/60sapi/实用功能/身体健康分析/styles.css b/InfoGenie-frontend/public/60sapi/实用功能/身体健康分析/styles.css similarity index 100% rename from frontend/public/60sapi/实用功能/身体健康分析/styles.css rename to InfoGenie-frontend/public/60sapi/实用功能/身体健康分析/styles.css diff --git a/frontend/public/60sapi/实用功能/身体健康分析/返回接口.json b/InfoGenie-frontend/public/60sapi/实用功能/身体健康分析/返回接口.json similarity index 100% rename from frontend/public/60sapi/实用功能/身体健康分析/返回接口.json rename to InfoGenie-frontend/public/60sapi/实用功能/身体健康分析/返回接口.json diff --git a/frontend/public/60sapi/实用功能/配色方案/background.css b/InfoGenie-frontend/public/60sapi/实用功能/配色方案/background.css similarity index 100% rename from frontend/public/60sapi/实用功能/配色方案/background.css rename to InfoGenie-frontend/public/60sapi/实用功能/配色方案/background.css diff --git a/frontend/public/60sapi/实用功能/配色方案/index.html b/InfoGenie-frontend/public/60sapi/实用功能/配色方案/index.html similarity index 100% rename from frontend/public/60sapi/实用功能/配色方案/index.html rename to InfoGenie-frontend/public/60sapi/实用功能/配色方案/index.html diff --git a/frontend/public/60sapi/实用功能/配色方案/script.js b/InfoGenie-frontend/public/60sapi/实用功能/配色方案/script.js similarity index 100% rename from frontend/public/60sapi/实用功能/配色方案/script.js rename to InfoGenie-frontend/public/60sapi/实用功能/配色方案/script.js diff --git a/frontend/public/60sapi/实用功能/配色方案/styles.css b/InfoGenie-frontend/public/60sapi/实用功能/配色方案/styles.css similarity index 100% rename from frontend/public/60sapi/实用功能/配色方案/styles.css rename to InfoGenie-frontend/public/60sapi/实用功能/配色方案/styles.css diff --git a/frontend/public/60sapi/实用功能/配色方案/返回接口.json b/InfoGenie-frontend/public/60sapi/实用功能/配色方案/返回接口.json similarity index 100% rename from frontend/public/60sapi/实用功能/配色方案/返回接口.json rename to InfoGenie-frontend/public/60sapi/实用功能/配色方案/返回接口.json diff --git a/frontend/public/60sapi/实用功能/链接OG信息/css/background.css b/InfoGenie-frontend/public/60sapi/实用功能/链接OG信息/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/链接OG信息/css/background.css rename to InfoGenie-frontend/public/60sapi/实用功能/链接OG信息/css/background.css diff --git a/frontend/public/60sapi/实用功能/链接OG信息/css/style.css b/InfoGenie-frontend/public/60sapi/实用功能/链接OG信息/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/链接OG信息/css/style.css rename to InfoGenie-frontend/public/60sapi/实用功能/链接OG信息/css/style.css diff --git a/frontend/public/60sapi/实用功能/链接OG信息/index.html b/InfoGenie-frontend/public/60sapi/实用功能/链接OG信息/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/链接OG信息/index.html rename to InfoGenie-frontend/public/60sapi/实用功能/链接OG信息/index.html diff --git a/frontend/public/60sapi/实用功能/链接OG信息/js/script.js b/InfoGenie-frontend/public/60sapi/实用功能/链接OG信息/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/链接OG信息/js/script.js rename to InfoGenie-frontend/public/60sapi/实用功能/链接OG信息/js/script.js diff --git a/frontend/public/60sapi/实用功能/链接OG信息/接口集合.json b/InfoGenie-frontend/public/60sapi/实用功能/链接OG信息/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/链接OG信息/接口集合.json rename to InfoGenie-frontend/public/60sapi/实用功能/链接OG信息/接口集合.json diff --git a/frontend/public/60sapi/实用功能/链接OG信息/返回接口.json b/InfoGenie-frontend/public/60sapi/实用功能/链接OG信息/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/实用功能/链接OG信息/返回接口.json rename to InfoGenie-frontend/public/60sapi/实用功能/链接OG信息/返回接口.json diff --git a/frontend/public/60sapi/实用功能/随机密码生成器/css/background.css b/InfoGenie-frontend/public/60sapi/实用功能/随机密码生成器/css/background.css similarity index 100% rename from frontend/public/60sapi/实用功能/随机密码生成器/css/background.css rename to InfoGenie-frontend/public/60sapi/实用功能/随机密码生成器/css/background.css diff --git a/frontend/public/60sapi/实用功能/随机密码生成器/css/style.css b/InfoGenie-frontend/public/60sapi/实用功能/随机密码生成器/css/style.css similarity index 100% rename from frontend/public/60sapi/实用功能/随机密码生成器/css/style.css rename to InfoGenie-frontend/public/60sapi/实用功能/随机密码生成器/css/style.css diff --git a/frontend/public/60sapi/实用功能/随机密码生成器/index.html b/InfoGenie-frontend/public/60sapi/实用功能/随机密码生成器/index.html similarity index 100% rename from frontend/public/60sapi/实用功能/随机密码生成器/index.html rename to InfoGenie-frontend/public/60sapi/实用功能/随机密码生成器/index.html diff --git a/frontend/public/60sapi/实用功能/随机密码生成器/js/script.js b/InfoGenie-frontend/public/60sapi/实用功能/随机密码生成器/js/script.js similarity index 100% rename from frontend/public/60sapi/实用功能/随机密码生成器/js/script.js rename to InfoGenie-frontend/public/60sapi/实用功能/随机密码生成器/js/script.js diff --git a/frontend/public/60sapi/实用功能/随机密码生成器/返回接口.json b/InfoGenie-frontend/public/60sapi/实用功能/随机密码生成器/返回接口.json similarity index 100% rename from frontend/public/60sapi/实用功能/随机密码生成器/返回接口.json rename to InfoGenie-frontend/public/60sapi/实用功能/随机密码生成器/返回接口.json diff --git a/frontend/public/60sapi/实用功能/随机颜色/background.css b/InfoGenie-frontend/public/60sapi/实用功能/随机颜色/background.css similarity index 100% rename from frontend/public/60sapi/实用功能/随机颜色/background.css rename to InfoGenie-frontend/public/60sapi/实用功能/随机颜色/background.css diff --git a/frontend/public/60sapi/实用功能/随机颜色/index.html b/InfoGenie-frontend/public/60sapi/实用功能/随机颜色/index.html similarity index 100% rename from frontend/public/60sapi/实用功能/随机颜色/index.html rename to InfoGenie-frontend/public/60sapi/实用功能/随机颜色/index.html diff --git a/frontend/public/60sapi/实用功能/随机颜色/script.js b/InfoGenie-frontend/public/60sapi/实用功能/随机颜色/script.js similarity index 100% rename from frontend/public/60sapi/实用功能/随机颜色/script.js rename to InfoGenie-frontend/public/60sapi/实用功能/随机颜色/script.js diff --git a/frontend/public/60sapi/实用功能/随机颜色/styles.css b/InfoGenie-frontend/public/60sapi/实用功能/随机颜色/styles.css similarity index 100% rename from frontend/public/60sapi/实用功能/随机颜色/styles.css rename to InfoGenie-frontend/public/60sapi/实用功能/随机颜色/styles.css diff --git a/frontend/public/60sapi/实用功能/随机颜色/返回接口.json b/InfoGenie-frontend/public/60sapi/实用功能/随机颜色/返回接口.json similarity index 100% rename from frontend/public/60sapi/实用功能/随机颜色/返回接口.json rename to InfoGenie-frontend/public/60sapi/实用功能/随机颜色/返回接口.json diff --git a/frontend/public/60sapi/日更资讯/历史上的今天/css/style.css b/InfoGenie-frontend/public/60sapi/日更资讯/历史上的今天/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/历史上的今天/css/style.css rename to InfoGenie-frontend/public/60sapi/日更资讯/历史上的今天/css/style.css diff --git a/frontend/public/60sapi/日更资讯/历史上的今天/index.html b/InfoGenie-frontend/public/60sapi/日更资讯/历史上的今天/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/历史上的今天/index.html rename to InfoGenie-frontend/public/60sapi/日更资讯/历史上的今天/index.html diff --git a/frontend/public/60sapi/日更资讯/历史上的今天/js/script.js b/InfoGenie-frontend/public/60sapi/日更资讯/历史上的今天/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/历史上的今天/js/script.js rename to InfoGenie-frontend/public/60sapi/日更资讯/历史上的今天/js/script.js diff --git a/frontend/public/60sapi/日更资讯/历史上的今天/接口集合.json b/InfoGenie-frontend/public/60sapi/日更资讯/历史上的今天/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/历史上的今天/接口集合.json rename to InfoGenie-frontend/public/60sapi/日更资讯/历史上的今天/接口集合.json diff --git a/frontend/public/60sapi/日更资讯/历史上的今天/返回接口.json b/InfoGenie-frontend/public/60sapi/日更资讯/历史上的今天/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/历史上的今天/返回接口.json rename to InfoGenie-frontend/public/60sapi/日更资讯/历史上的今天/返回接口.json diff --git a/frontend/public/60sapi/日更资讯/必应每日壁纸/css/style.css b/InfoGenie-frontend/public/60sapi/日更资讯/必应每日壁纸/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/必应每日壁纸/css/style.css rename to InfoGenie-frontend/public/60sapi/日更资讯/必应每日壁纸/css/style.css diff --git a/frontend/public/60sapi/日更资讯/必应每日壁纸/index.html b/InfoGenie-frontend/public/60sapi/日更资讯/必应每日壁纸/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/必应每日壁纸/index.html rename to InfoGenie-frontend/public/60sapi/日更资讯/必应每日壁纸/index.html diff --git a/frontend/public/60sapi/日更资讯/必应每日壁纸/js/script.js b/InfoGenie-frontend/public/60sapi/日更资讯/必应每日壁纸/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/必应每日壁纸/js/script.js rename to InfoGenie-frontend/public/60sapi/日更资讯/必应每日壁纸/js/script.js diff --git a/frontend/public/60sapi/日更资讯/必应每日壁纸/接口集合.json b/InfoGenie-frontend/public/60sapi/日更资讯/必应每日壁纸/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/必应每日壁纸/接口集合.json rename to InfoGenie-frontend/public/60sapi/日更资讯/必应每日壁纸/接口集合.json diff --git a/frontend/public/60sapi/日更资讯/必应每日壁纸/返回接口.json b/InfoGenie-frontend/public/60sapi/日更资讯/必应每日壁纸/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/必应每日壁纸/返回接口.json rename to InfoGenie-frontend/public/60sapi/日更资讯/必应每日壁纸/返回接口.json diff --git a/frontend/public/60sapi/日更资讯/每天60s读懂世界/css/style.css b/InfoGenie-frontend/public/60sapi/日更资讯/每天60s读懂世界/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/每天60s读懂世界/css/style.css rename to InfoGenie-frontend/public/60sapi/日更资讯/每天60s读懂世界/css/style.css diff --git a/frontend/public/60sapi/日更资讯/每天60s读懂世界/index.html b/InfoGenie-frontend/public/60sapi/日更资讯/每天60s读懂世界/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/每天60s读懂世界/index.html rename to InfoGenie-frontend/public/60sapi/日更资讯/每天60s读懂世界/index.html diff --git a/frontend/public/60sapi/日更资讯/每天60s读懂世界/js/script.js b/InfoGenie-frontend/public/60sapi/日更资讯/每天60s读懂世界/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/每天60s读懂世界/js/script.js rename to InfoGenie-frontend/public/60sapi/日更资讯/每天60s读懂世界/js/script.js diff --git a/frontend/public/60sapi/日更资讯/每天60s读懂世界/接口集合.json b/InfoGenie-frontend/public/60sapi/日更资讯/每天60s读懂世界/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/每天60s读懂世界/接口集合.json rename to InfoGenie-frontend/public/60sapi/日更资讯/每天60s读懂世界/接口集合.json diff --git a/frontend/public/60sapi/日更资讯/每天60s读懂世界/返回接口.json b/InfoGenie-frontend/public/60sapi/日更资讯/每天60s读懂世界/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/每天60s读懂世界/返回接口.json rename to InfoGenie-frontend/public/60sapi/日更资讯/每天60s读懂世界/返回接口.json diff --git a/frontend/public/60sapi/日更资讯/每日国际汇率/css/style.css b/InfoGenie-frontend/public/60sapi/日更资讯/每日国际汇率/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/每日国际汇率/css/style.css rename to InfoGenie-frontend/public/60sapi/日更资讯/每日国际汇率/css/style.css diff --git a/frontend/public/60sapi/日更资讯/每日国际汇率/index.html b/InfoGenie-frontend/public/60sapi/日更资讯/每日国际汇率/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/每日国际汇率/index.html rename to InfoGenie-frontend/public/60sapi/日更资讯/每日国际汇率/index.html diff --git a/frontend/public/60sapi/日更资讯/每日国际汇率/js/script.js b/InfoGenie-frontend/public/60sapi/日更资讯/每日国际汇率/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/每日国际汇率/js/script.js rename to InfoGenie-frontend/public/60sapi/日更资讯/每日国际汇率/js/script.js diff --git a/frontend/public/60sapi/日更资讯/每日国际汇率/接口集合.json b/InfoGenie-frontend/public/60sapi/日更资讯/每日国际汇率/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/每日国际汇率/接口集合.json rename to InfoGenie-frontend/public/60sapi/日更资讯/每日国际汇率/接口集合.json diff --git a/frontend/public/60sapi/日更资讯/每日国际汇率/返回接口.json b/InfoGenie-frontend/public/60sapi/日更资讯/每日国际汇率/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/日更资讯/每日国际汇率/返回接口.json rename to InfoGenie-frontend/public/60sapi/日更资讯/每日国际汇率/返回接口.json diff --git a/frontend/public/60sapi/热搜榜单/Hacker News 榜单/css/background.css b/InfoGenie-frontend/public/60sapi/热搜榜单/Hacker News 榜单/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/Hacker News 榜单/css/background.css rename to InfoGenie-frontend/public/60sapi/热搜榜单/Hacker News 榜单/css/background.css diff --git a/frontend/public/60sapi/热搜榜单/Hacker News 榜单/css/style.css b/InfoGenie-frontend/public/60sapi/热搜榜单/Hacker News 榜单/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/Hacker News 榜单/css/style.css rename to InfoGenie-frontend/public/60sapi/热搜榜单/Hacker News 榜单/css/style.css diff --git a/frontend/public/60sapi/热搜榜单/Hacker News 榜单/index.html b/InfoGenie-frontend/public/60sapi/热搜榜单/Hacker News 榜单/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/Hacker News 榜单/index.html rename to InfoGenie-frontend/public/60sapi/热搜榜单/Hacker News 榜单/index.html diff --git a/frontend/public/60sapi/热搜榜单/Hacker News 榜单/js/script.js b/InfoGenie-frontend/public/60sapi/热搜榜单/Hacker News 榜单/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/Hacker News 榜单/js/script.js rename to InfoGenie-frontend/public/60sapi/热搜榜单/Hacker News 榜单/js/script.js diff --git a/frontend/public/60sapi/热搜榜单/Hacker News 榜单/接口集合.json b/InfoGenie-frontend/public/60sapi/热搜榜单/Hacker News 榜单/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/Hacker News 榜单/接口集合.json rename to InfoGenie-frontend/public/60sapi/热搜榜单/Hacker News 榜单/接口集合.json diff --git a/frontend/public/60sapi/热搜榜单/Hacker News 榜单/返回接口.json b/InfoGenie-frontend/public/60sapi/热搜榜单/Hacker News 榜单/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/Hacker News 榜单/返回接口.json rename to InfoGenie-frontend/public/60sapi/热搜榜单/Hacker News 榜单/返回接口.json diff --git a/frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/css/background.css b/InfoGenie-frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/css/background.css rename to InfoGenie-frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/css/background.css diff --git a/frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/css/style.css b/InfoGenie-frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/css/style.css rename to InfoGenie-frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/css/style.css diff --git a/frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/index.html b/InfoGenie-frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/index.html rename to InfoGenie-frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/index.html diff --git a/frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/js/main.js b/InfoGenie-frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/js/main.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/js/main.js rename to InfoGenie-frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/js/main.js diff --git a/frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/接口集合.json b/InfoGenie-frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/接口集合.json rename to InfoGenie-frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/接口集合.json diff --git a/frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/返回接口.json b/InfoGenie-frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/返回接口.json rename to InfoGenie-frontend/public/60sapi/热搜榜单/哔哩哔哩热搜榜/返回接口.json diff --git a/frontend/public/60sapi/热搜榜单/头条热搜榜/css/background.css b/InfoGenie-frontend/public/60sapi/热搜榜单/头条热搜榜/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/头条热搜榜/css/background.css rename to InfoGenie-frontend/public/60sapi/热搜榜单/头条热搜榜/css/background.css diff --git a/frontend/public/60sapi/热搜榜单/头条热搜榜/css/style.css b/InfoGenie-frontend/public/60sapi/热搜榜单/头条热搜榜/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/头条热搜榜/css/style.css rename to InfoGenie-frontend/public/60sapi/热搜榜单/头条热搜榜/css/style.css diff --git a/frontend/public/60sapi/热搜榜单/头条热搜榜/index.html b/InfoGenie-frontend/public/60sapi/热搜榜单/头条热搜榜/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/头条热搜榜/index.html rename to InfoGenie-frontend/public/60sapi/热搜榜单/头条热搜榜/index.html diff --git a/frontend/public/60sapi/热搜榜单/头条热搜榜/js/main.js b/InfoGenie-frontend/public/60sapi/热搜榜单/头条热搜榜/js/main.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/头条热搜榜/js/main.js rename to InfoGenie-frontend/public/60sapi/热搜榜单/头条热搜榜/js/main.js diff --git a/frontend/public/60sapi/热搜榜单/头条热搜榜/接口集合.json b/InfoGenie-frontend/public/60sapi/热搜榜单/头条热搜榜/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/头条热搜榜/接口集合.json rename to InfoGenie-frontend/public/60sapi/热搜榜单/头条热搜榜/接口集合.json diff --git a/frontend/public/60sapi/热搜榜单/头条热搜榜/返回接口.json b/InfoGenie-frontend/public/60sapi/热搜榜单/头条热搜榜/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/头条热搜榜/返回接口.json rename to InfoGenie-frontend/public/60sapi/热搜榜单/头条热搜榜/返回接口.json diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/小红书热点/background.css b/InfoGenie-frontend/public/60sapi/热搜榜单/小红书热点/background.css new file mode 100644 index 00000000..8a5a8569 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/小红书热点/background.css @@ -0,0 +1,144 @@ +/* 背景样式文件 - 独立管理所有背景相关样式 */ + +/* 页面主背景 */ +body { + background: linear-gradient(135deg, #f8fffe 0%, #f0f9f4 50%, #e8f5e8 100%); + background-attachment: fixed; + background-size: cover; + position: relative; +} + +/* 背景装饰元素 */ +body::before { + content: ''; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-image: + radial-gradient(circle at 20% 80%, rgba(168, 230, 207, 0.1) 0%, transparent 50%), + radial-gradient(circle at 80% 20%, rgba(39, 174, 96, 0.08) 0%, transparent 50%), + radial-gradient(circle at 40% 40%, rgba(46, 204, 113, 0.05) 0%, transparent 50%); + pointer-events: none; + z-index: -1; +} + +/* 容器背景 */ +.container { + background: rgba(255, 255, 255, 0.7); + backdrop-filter: blur(10px); + border-radius: 20px; + margin-top: 20px; + margin-bottom: 20px; + box-shadow: 0 8px 32px rgba(39, 174, 96, 0.1); +} + +/* 头部背景 */ +.header { + background: linear-gradient(135deg, rgba(168, 230, 207, 0.2) 0%, rgba(39, 174, 96, 0.1) 100%); + border-radius: 20px 20px 0 0; + position: relative; + overflow: hidden; +} + +.header::before { + content: ''; + position: absolute; + top: -50%; + left: -50%; + width: 200%; + height: 200%; + background: radial-gradient(circle, rgba(39, 174, 96, 0.05) 0%, transparent 70%); + animation: float 6s ease-in-out infinite; +} + +@keyframes float { + 0%, 100% { + transform: translate(0, 0) rotate(0deg); + } + 50% { + transform: translate(-10px, -10px) rotate(180deg); + } +} + +/* 热点项目背景 */ +.hot-item { + background: rgba(255, 255, 255, 0.9); + backdrop-filter: blur(5px); + position: relative; +} + +.hot-item::after { + content: ''; + position: absolute; + top: 0; + right: 0; + width: 60px; + height: 60px; + background: radial-gradient(circle, rgba(168, 230, 207, 0.1) 0%, transparent 70%); + border-radius: 50%; + transform: translate(30px, -30px); + pointer-events: none; +} + +/* 前三名特殊背景效果 */ +.hot-item:nth-child(1) { + background: linear-gradient(135deg, rgba(255, 215, 0, 0.1) 0%, rgba(255, 255, 255, 0.9) 100%); +} + +.hot-item:nth-child(2) { + background: linear-gradient(135deg, rgba(192, 192, 192, 0.1) 0%, rgba(255, 255, 255, 0.9) 100%); +} + +.hot-item:nth-child(3) { + background: linear-gradient(135deg, rgba(205, 127, 50, 0.1) 0%, rgba(255, 255, 255, 0.9) 100%); +} + +/* 底部背景 */ +.footer { + background: linear-gradient(135deg, rgba(168, 230, 207, 0.1) 0%, rgba(39, 174, 96, 0.05) 100%); + border-radius: 0 0 20px 20px; +} + +/* 加载状态背景 */ +.loading { + background: rgba(255, 255, 255, 0.8); + border-radius: 12px; + backdrop-filter: blur(5px); +} + +/* 错误信息背景 */ +.error-message { + background: rgba(255, 255, 255, 0.9); + border: 1px solid rgba(231, 76, 60, 0.2); + border-radius: 12px; + backdrop-filter: blur(5px); +} + +/* 响应式背景调整 */ +@media (max-width: 768px) { + .container { + margin-top: 10px; + margin-bottom: 10px; + border-radius: 16px; + } + + .header { + border-radius: 16px 16px 0 0; + } + + .footer { + border-radius: 0 0 16px 16px; + } +} + +@media (min-width: 1025px) { + body::before { + background-image: + radial-gradient(circle at 15% 85%, rgba(168, 230, 207, 0.15) 0%, transparent 50%), + radial-gradient(circle at 85% 15%, rgba(39, 174, 96, 0.12) 0%, transparent 50%), + radial-gradient(circle at 50% 50%, rgba(46, 204, 113, 0.08) 0%, transparent 50%), + radial-gradient(circle at 25% 25%, rgba(168, 230, 207, 0.06) 0%, transparent 50%); + } +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/小红书热点/index.html b/InfoGenie-frontend/public/60sapi/热搜榜单/小红书热点/index.html new file mode 100644 index 00000000..007cfc91 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/小红书热点/index.html @@ -0,0 +1,40 @@ + + + + + + 小红书热点榜单 + + + + +
+
+

小红书热点榜单

+

实时热门话题,发现精彩内容

+
+ +
+
+
+

正在加载热点数据...

+
+ + + + +
+ +
+

+
+
+ + + + \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/小红书热点/script.js b/InfoGenie-frontend/public/60sapi/热搜榜单/小红书热点/script.js new file mode 100644 index 00000000..5fcd322c --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/小红书热点/script.js @@ -0,0 +1,180 @@ +// 小红书热点榜单 JavaScript 逻辑 + +// DOM 元素 +const loadingEl = document.getElementById('loading'); +const errorEl = document.getElementById('error'); +const hotListEl = document.getElementById('hotList'); +const updateTimeEl = document.getElementById('updateTime'); + +// 页面加载完成后初始化 +document.addEventListener('DOMContentLoaded', function() { + loadData(); +}); + +// 加载数据函数 +async function loadData() { + try { + showLoading(); + + // 从API接口获取数据 + const response = await fetch('https://60s.api.shumengya.top/v2/rednote'); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + + if (data.code === 200 && data.data) { + renderHotList(data.data); + updateTime(); + showSuccess(); + } else { + throw new Error('数据格式错误'); + } + + } catch (error) { + console.error('加载数据失败:', error); + showError(); + } +} + +// 显示加载状态 +function showLoading() { + loadingEl.style.display = 'block'; + errorEl.style.display = 'none'; + hotListEl.style.display = 'none'; +} + +// 显示错误状态 +function showError() { + loadingEl.style.display = 'none'; + errorEl.style.display = 'block'; + hotListEl.style.display = 'none'; +} + +// 显示成功状态 +function showSuccess() { + loadingEl.style.display = 'none'; + errorEl.style.display = 'none'; + hotListEl.style.display = 'block'; +} + +// 渲染热点列表 +function renderHotList(hotData) { + hotListEl.innerHTML = ''; + + hotData.forEach((item, index) => { + const hotItem = createHotItem(item, index); + hotListEl.appendChild(hotItem); + }); +} + +// 创建热点项目元素 +function createHotItem(item, index) { + const itemEl = document.createElement('div'); + itemEl.className = 'hot-item'; + + // 添加点击事件 + itemEl.addEventListener('click', () => { + if (item.link) { + window.open(item.link, '_blank'); + } + }); + + // 构建HTML内容 + itemEl.innerHTML = ` +
+
${item.rank}
+
+ ${item.work_type_icon ? `${item.word_type}` : ''} + ${item.word_type && item.word_type !== '无' ? `${item.word_type}` : ''} +
+
+
+

${escapeHtml(item.title)}

+

热度: ${item.score}

+
+ `; + + return itemEl; +} + +// 获取类型样式类名 +function getTypeClass(wordType) { + switch (wordType) { + case '热': + return 'hot'; + case '新': + return 'new'; + default: + return 'default'; + } +} + +// HTML转义函数 +function escapeHtml(text) { + const div = document.createElement('div'); + div.textContent = text; + return div.innerHTML; +} + +// 更新时间显示 +function updateTime() { + const now = new Date(); + const timeString = now.toLocaleString('zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + }); + updateTimeEl.textContent = `最后更新: ${timeString}`; +} + +// 添加页面可见性变化监听,当页面重新可见时刷新数据 +document.addEventListener('visibilitychange', function() { + if (!document.hidden) { + // 页面变为可见时,延迟1秒后刷新数据 + setTimeout(() => { + loadData(); + }, 1000); + } +}); + +// 添加网络状态监听 +window.addEventListener('online', function() { + // 网络恢复时自动重新加载 + setTimeout(() => { + loadData(); + }, 500); +}); + +// 添加错误处理 +window.addEventListener('error', function(e) { + console.error('页面错误:', e.error); +}); + +// 添加未处理的Promise拒绝监听 +window.addEventListener('unhandledrejection', function(e) { + console.error('未处理的Promise拒绝:', e.reason); + e.preventDefault(); +}); + +// 添加触摸设备的优化 +if ('ontouchstart' in window) { + // 为触摸设备添加触摸反馈 + document.addEventListener('touchstart', function() {}, { passive: true }); +} + +// 添加键盘导航支持 +document.addEventListener('keydown', function(e) { + if (e.key === 'F5' || (e.ctrlKey && e.key === 'r')) { + e.preventDefault(); + loadData(); + } +}); + +// 导出函数供全局使用 +window.loadData = loadData; \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/小红书热点/styles.css b/InfoGenie-frontend/public/60sapi/热搜榜单/小红书热点/styles.css new file mode 100644 index 00000000..a9385421 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/小红书热点/styles.css @@ -0,0 +1,299 @@ +/* 基础样式重置 */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; + line-height: 1.6; + color: #2c3e50; + overflow-x: hidden; +} + +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 16px; + min-height: 100vh; + display: flex; + flex-direction: column; +} + +/* 头部样式 */ +.header { + text-align: center; + padding: 24px 0; + border-bottom: 2px solid #a8e6cf; + margin-bottom: 24px; +} + +.title { + font-size: 28px; + font-weight: 700; + color: #27ae60; + margin-bottom: 8px; + text-shadow: 0 2px 4px rgba(39, 174, 96, 0.1); +} + +.subtitle { + font-size: 14px; + color: #7f8c8d; + font-weight: 400; +} + +/* 主内容区域 */ +.main-content { + flex: 1; + position: relative; +} + +/* 加载状态 */ +.loading { + text-align: center; + padding: 60px 20px; + color: #27ae60; +} + +.loading-spinner { + width: 40px; + height: 40px; + border: 3px solid #a8e6cf; + border-top: 3px solid #27ae60; + border-radius: 50%; + animation: spin 1s linear infinite; + margin: 0 auto 16px; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* 错误信息 */ +.error-message { + text-align: center; + padding: 40px 20px; + color: #e74c3c; +} + +.retry-btn { + background: #27ae60; + color: white; + border: none; + padding: 10px 20px; + border-radius: 20px; + cursor: pointer; + font-size: 14px; + margin-top: 16px; + transition: background 0.3s ease; +} + +.retry-btn:hover { + background: #219a52; +} + +/* 热点列表 */ +.hot-list { + display: grid; + gap: 12px; +} + +.hot-item { + background: #ffffff; + border: 1px solid #e8f5e8; + border-radius: 12px; + padding: 16px; + transition: all 0.3s ease; + box-shadow: 0 2px 8px rgba(39, 174, 96, 0.08); + position: relative; + overflow: hidden; +} + +.hot-item:hover { + transform: translateY(-2px); + box-shadow: 0 4px 16px rgba(39, 174, 96, 0.15); + border-color: #a8e6cf; +} + +.hot-item::before { + content: ''; + position: absolute; + left: 0; + top: 0; + width: 4px; + height: 100%; + background: linear-gradient(to bottom, #27ae60, #a8e6cf); +} + +.item-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 8px; +} + +.rank { + background: linear-gradient(135deg, #27ae60, #2ecc71); + color: white; + width: 28px; + height: 28px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + font-size: 14px; + flex-shrink: 0; +} + +.rank.top3 { + background: linear-gradient(135deg, #f39c12, #e67e22); +} + +.word-type { + display: flex; + align-items: center; + gap: 4px; +} + +.type-icon { + width: 16px; + height: 16px; + object-fit: contain; +} + +.type-text { + font-size: 12px; + padding: 2px 8px; + border-radius: 10px; + font-weight: 500; +} + +.type-hot { + background: #ffe6e6; + color: #e74c3c; +} + +.type-new { + background: #e6f3ff; + color: #3498db; +} + +.item-content { + margin-bottom: 8px; +} + +.item-title { + font-size: 16px; + font-weight: 600; + color: #2c3e50; + line-height: 1.4; + margin-bottom: 4px; + cursor: pointer; + transition: color 0.3s ease; +} + +.item-title:hover { + color: #27ae60; +} + +.item-score { + font-size: 14px; + color: #7f8c8d; + font-weight: 500; +} + +/* 底部 */ +.footer { + text-align: center; + padding: 24px 0; + border-top: 1px solid #e8f5e8; + margin-top: 32px; +} + +.update-time { + font-size: 12px; + color: #95a5a6; +} + +/* 手机端优化 (默认) */ +@media (max-width: 768px) { + .container { + padding: 0 12px; + } + + .header { + padding: 20px 0; + } + + .title { + font-size: 24px; + } + + .subtitle { + font-size: 13px; + } + + .hot-item { + padding: 14px; + } + + .item-title { + font-size: 15px; + } + + .rank { + width: 26px; + height: 26px; + font-size: 13px; + } +} + +/* 平板端适配 */ +@media (min-width: 769px) and (max-width: 1024px) { + .container { + padding: 0 24px; + } + + .hot-list { + grid-template-columns: repeat(2, 1fr); + gap: 16px; + } + + .title { + font-size: 32px; + } +} + +/* 电脑端适配 */ +@media (min-width: 1025px) { + .container { + padding: 0 32px; + } + + .hot-list { + grid-template-columns: repeat(2, 1fr); + gap: 20px; + } + + .title { + font-size: 36px; + } + + .hot-item { + padding: 20px; + } + + .item-title { + font-size: 17px; + } +} + +/* 大屏幕优化 */ +@media (min-width: 1400px) { + .hot-list { + grid-template-columns: repeat(3, 1fr); + } +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/小红书热点/返回接口.json b/InfoGenie-frontend/public/60sapi/热搜榜单/小红书热点/返回接口.json new file mode 100644 index 00000000..493aa294 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/小红书热点/返回接口.json @@ -0,0 +1,166 @@ +{ + "code": 200, + "message": "获取成功。数据来自官方/权威源头,以确保稳定与实时。开源地址 https://github.com/vikiboss/60s,反馈群 595941841", + "data": [ + { + "rank": 1, + "title": "九三阅兵", + "score": "908.5w", + "word_type": "热", + "work_type_icon": "https://picasso-static.xiaohongshu.com/fe-platform/cfd317ff14757c7ede6ef5176ec487589565e49e.png", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E4%B9%9D%E4%B8%89%E9%98%85%E5%85%B5&type=51" + }, + { + "rank": 2, + "title": "我镜头下的中式建筑美学", + "score": "872.9w", + "word_type": "新", + "work_type_icon": "https://sns-img-qc.xhscdn.com/search/trends/icon/label/new/version/1", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E6%88%91%E9%95%9C%E5%A4%B4%E4%B8%8B%E7%9A%84%E4%B8%AD%E5%BC%8F%E5%BB%BA%E7%AD%91%E7%BE%8E%E5%AD%A6&type=51" + }, + { + "rank": 3, + "title": "原来人机感才是出片的秘诀", + "score": "754.4w", + "word_type": "无", + "work_type_icon": "", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E5%8E%9F%E6%9D%A5%E4%BA%BA%E6%9C%BA%E6%84%9F%E6%89%8D%E6%98%AF%E5%87%BA%E7%89%87%E7%9A%84%E7%A7%98%E8%AF%80&type=51" + }, + { + "rank": 4, + "title": "我的二十年航天路", + "score": "703.9w", + "word_type": "热", + "work_type_icon": "https://picasso-static.xiaohongshu.com/fe-platform/cfd317ff14757c7ede6ef5176ec487589565e49e.png", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E6%88%91%E7%9A%84%E4%BA%8C%E5%8D%81%E5%B9%B4%E8%88%AA%E5%A4%A9%E8%B7%AF&type=51" + }, + { + "rank": 5, + "title": "用横图的方式打开香格里拉", + "score": "458.5w", + "word_type": "新", + "work_type_icon": "https://sns-img-qc.xhscdn.com/search/trends/icon/label/new/version/1", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E7%94%A8%E6%A8%AA%E5%9B%BE%E7%9A%84%E6%96%B9%E5%BC%8F%E6%89%93%E5%BC%80%E9%A6%99%E6%A0%BC%E9%87%8C%E6%8B%89&type=51" + }, + { + "rank": 6, + "title": "我拍到了苏州丰收的景象", + "score": "392w", + "word_type": "无", + "work_type_icon": "", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E6%88%91%E6%8B%8D%E5%88%B0%E4%BA%86%E8%8B%8F%E5%B7%9E%E4%B8%B0%E6%94%B6%E7%9A%84%E6%99%AF%E8%B1%A1&type=51" + }, + { + "rank": 7, + "title": "我拍下了960万平方公里的中国", + "score": "390.7w", + "word_type": "热", + "work_type_icon": "https://picasso-static.xiaohongshu.com/fe-platform/cfd317ff14757c7ede6ef5176ec487589565e49e.png", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E6%88%91%E6%8B%8D%E4%B8%8B%E4%BA%86960%E4%B8%87%E5%B9%B3%E6%96%B9%E5%85%AC%E9%87%8C%E7%9A%84%E4%B8%AD%E5%9B%BD&type=51" + }, + { + "rank": 8, + "title": "12岁冰岛少年的川剧变脸梦", + "score": "389.7w", + "word_type": "热", + "work_type_icon": "https://picasso-static.xiaohongshu.com/fe-platform/cfd317ff14757c7ede6ef5176ec487589565e49e.png", + "link": "https://www.xiaohongshu.com/search_result?keyword=12%E5%B2%81%E5%86%B0%E5%B2%9B%E5%B0%91%E5%B9%B4%E7%9A%84%E5%B7%9D%E5%89%A7%E5%8F%98%E8%84%B8%E6%A2%A6&type=51" + }, + { + "rank": 9, + "title": "人生总要去一次阿勒泰吧", + "score": "389.6w", + "word_type": "新", + "work_type_icon": "https://sns-img-qc.xhscdn.com/search/trends/icon/label/new/version/1", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E4%BA%BA%E7%94%9F%E6%80%BB%E8%A6%81%E5%8E%BB%E4%B8%80%E6%AC%A1%E9%98%BF%E5%8B%92%E6%B3%B0%E5%90%A7&type=51" + }, + { + "rank": 10, + "title": "普通人的10年绘画进步史", + "score": "389.4w", + "word_type": "无", + "work_type_icon": "", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E6%99%AE%E9%80%9A%E4%BA%BA%E7%9A%8410%E5%B9%B4%E7%BB%98%E7%94%BB%E8%BF%9B%E6%AD%A5%E5%8F%B2&type=51" + }, + { + "rank": 11, + "title": "过生日不要忘记反转镜头", + "score": "389.2w", + "word_type": "热", + "work_type_icon": "https://picasso-static.xiaohongshu.com/fe-platform/cfd317ff14757c7ede6ef5176ec487589565e49e.png", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E8%BF%87%E7%94%9F%E6%97%A5%E4%B8%8D%E8%A6%81%E5%BF%98%E8%AE%B0%E5%8F%8D%E8%BD%AC%E9%95%9C%E5%A4%B4&type=51" + }, + { + "rank": 12, + "title": "低卡又解馋的报恩零食", + "score": "389.2w", + "word_type": "无", + "work_type_icon": "", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E4%BD%8E%E5%8D%A1%E5%8F%88%E8%A7%A3%E9%A6%8B%E7%9A%84%E6%8A%A5%E6%81%A9%E9%9B%B6%E9%A3%9F&type=51" + }, + { + "rank": 13, + "title": "和爸妈去旅游 我是水印", + "score": "389w", + "word_type": "新", + "work_type_icon": "https://sns-img-qc.xhscdn.com/search/trends/icon/label/new/version/1", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E5%92%8C%E7%88%B8%E5%A6%88%E5%8E%BB%E6%97%85%E6%B8%B8%20%E6%88%91%E6%98%AF%E6%B0%B4%E5%8D%B0&type=51" + }, + { + "rank": 14, + "title": "一种很新的镜子拍谷法出现了", + "score": "389w", + "word_type": "热", + "work_type_icon": "https://picasso-static.xiaohongshu.com/fe-platform/cfd317ff14757c7ede6ef5176ec487589565e49e.png", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E4%B8%80%E7%A7%8D%E5%BE%88%E6%96%B0%E7%9A%84%E9%95%9C%E5%AD%90%E6%8B%8D%E8%B0%B7%E6%B3%95%E5%87%BA%E7%8E%B0%E4%BA%86&type=51" + }, + { + "rank": 15, + "title": "二次构图带来的故事感", + "score": "389w", + "word_type": "无", + "work_type_icon": "", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E4%BA%8C%E6%AC%A1%E6%9E%84%E5%9B%BE%E5%B8%A6%E6%9D%A5%E7%9A%84%E6%95%85%E4%BA%8B%E6%84%9F&type=51" + }, + { + "rank": 16, + "title": "当我在老动画片里找美妆灵感", + "score": "389w", + "word_type": "无", + "work_type_icon": "", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E5%BD%93%E6%88%91%E5%9C%A8%E8%80%81%E5%8A%A8%E7%94%BB%E7%89%87%E9%87%8C%E6%89%BE%E7%BE%8E%E5%A6%86%E7%81%B5%E6%84%9F&type=51" + }, + { + "rank": 17, + "title": "在蓝调时刻起舞告别夏天", + "score": "389w", + "word_type": "热", + "work_type_icon": "https://picasso-static.xiaohongshu.com/fe-platform/cfd317ff14757c7ede6ef5176ec487589565e49e.png", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E5%9C%A8%E8%93%9D%E8%B0%83%E6%97%B6%E5%88%BB%E8%B5%B7%E8%88%9E%E5%91%8A%E5%88%AB%E5%A4%8F%E5%A4%A9&type=51" + }, + { + "rank": 18, + "title": "人生建议:去看一次鱼灯巡游", + "score": "389w", + "word_type": "无", + "work_type_icon": "", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E4%BA%BA%E7%94%9F%E5%BB%BA%E8%AE%AE%EF%BC%9A%E5%8E%BB%E7%9C%8B%E4%B8%80%E6%AC%A1%E9%B1%BC%E7%81%AF%E5%B7%A1%E6%B8%B8&type=51" + }, + { + "rank": 19, + "title": "夜晚的树是大自然送给天空的星星", + "score": "389w", + "word_type": "新", + "work_type_icon": "https://sns-img-qc.xhscdn.com/search/trends/icon/label/new/version/1", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E5%A4%9C%E6%99%9A%E7%9A%84%E6%A0%91%E6%98%AF%E5%A4%A7%E8%87%AA%E7%84%B6%E9%80%81%E7%BB%99%E5%A4%A9%E7%A9%BA%E7%9A%84%E6%98%9F%E6%98%9F&type=51" + }, + { + "rank": 20, + "title": "欢迎收看老师开学的一天", + "score": "389w", + "word_type": "无", + "work_type_icon": "", + "link": "https://www.xiaohongshu.com/search_result?keyword=%E6%AC%A2%E8%BF%8E%E6%94%B6%E7%9C%8B%E8%80%81%E5%B8%88%E5%BC%80%E5%AD%A6%E7%9A%84%E4%B8%80%E5%A4%A9&type=51" + } + ] +} \ No newline at end of file diff --git a/frontend/public/60sapi/热搜榜单/微博热搜榜/css/background.css b/InfoGenie-frontend/public/60sapi/热搜榜单/微博热搜榜/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/微博热搜榜/css/background.css rename to InfoGenie-frontend/public/60sapi/热搜榜单/微博热搜榜/css/background.css diff --git a/frontend/public/60sapi/热搜榜单/微博热搜榜/css/style.css b/InfoGenie-frontend/public/60sapi/热搜榜单/微博热搜榜/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/微博热搜榜/css/style.css rename to InfoGenie-frontend/public/60sapi/热搜榜单/微博热搜榜/css/style.css diff --git a/frontend/public/60sapi/热搜榜单/微博热搜榜/img/qeye.svg b/InfoGenie-frontend/public/60sapi/热搜榜单/微博热搜榜/img/qeye.svg old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/微博热搜榜/img/qeye.svg rename to InfoGenie-frontend/public/60sapi/热搜榜单/微博热搜榜/img/qeye.svg diff --git a/frontend/public/60sapi/热搜榜单/微博热搜榜/index.html b/InfoGenie-frontend/public/60sapi/热搜榜单/微博热搜榜/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/微博热搜榜/index.html rename to InfoGenie-frontend/public/60sapi/热搜榜单/微博热搜榜/index.html diff --git a/frontend/public/60sapi/热搜榜单/微博热搜榜/js/main.js b/InfoGenie-frontend/public/60sapi/热搜榜单/微博热搜榜/js/main.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/微博热搜榜/js/main.js rename to InfoGenie-frontend/public/60sapi/热搜榜单/微博热搜榜/js/main.js diff --git a/frontend/public/60sapi/热搜榜单/微博热搜榜/接口集合.json b/InfoGenie-frontend/public/60sapi/热搜榜单/微博热搜榜/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/微博热搜榜/接口集合.json rename to InfoGenie-frontend/public/60sapi/热搜榜单/微博热搜榜/接口集合.json diff --git a/frontend/public/60sapi/热搜榜单/微博热搜榜/返回接口.json b/InfoGenie-frontend/public/60sapi/热搜榜单/微博热搜榜/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/微博热搜榜/返回接口.json rename to InfoGenie-frontend/public/60sapi/热搜榜单/微博热搜榜/返回接口.json diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/api.js b/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/api.js new file mode 100644 index 00000000..a5ec529e --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/api.js @@ -0,0 +1,180 @@ +/** + * 懂车帝热搜API模块 + * 负责数据获取、验证和格式化 + */ +class CarHotTopicsAPI { + constructor() { + this.baseURL = 'https://60s.api.shumengya.top/v2/dongchedi'; + this.timeout = 10000; // 10秒超时 + this.retryCount = 3; + this.retryDelay = 1000; // 1秒重试延迟 + } + + /** + * 获取热搜数据 + * @param {string} encoding - 编码格式(可选) + * @returns {Promise} 热搜数据 + */ + async fetchHotTopics(encoding = '') { + const url = encoding ? `${this.baseURL}?encoding=${encodeURIComponent(encoding)}` : this.baseURL; + + for (let attempt = 1; attempt <= this.retryCount; attempt++) { + try { + console.log(`[API] 尝试获取数据 (${attempt}/${this.retryCount}): ${url}`); + + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), this.timeout); + + const response = await fetch(url, { + method: 'GET', + headers: { + 'Accept': 'application/json', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' + }, + signal: controller.signal + }); + + clearTimeout(timeoutId); + + if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${response.statusText}`); + } + + const data = await response.json(); + console.log('[API] 数据获取成功:', data); + + // 验证数据格式 + const validatedData = this.validateData(data); + return this.formatData(validatedData); + + } catch (error) { + console.error(`[API] 第${attempt}次请求失败:`, error.message); + + if (attempt === this.retryCount) { + throw new Error(`获取数据失败: ${error.message}`); + } + + // 等待后重试 + await this.delay(this.retryDelay * attempt); + } + } + } + + /** + * 验证API返回数据格式 + * @param {Object} data - API返回的原始数据 + * @returns {Object} 验证后的数据 + */ + validateData(data) { + if (!data || typeof data !== 'object') { + throw new Error('数据格式错误:响应不是有效的JSON对象'); + } + + if (data.code !== 200) { + throw new Error(`API错误:${data.message || '未知错误'}`); + } + + if (!Array.isArray(data.data)) { + throw new Error('数据格式错误:data字段不是数组'); + } + + // 验证每个热搜项目的必需字段 + data.data.forEach((item, index) => { + const requiredFields = ['rank', 'title', 'score', 'score_desc']; + const missingFields = requiredFields.filter(field => !(field in item)); + + if (missingFields.length > 0) { + console.warn(`[API] 第${index + 1}项数据缺少字段:`, missingFields); + } + }); + + return data; + } + + /** + * 格式化数据 + * @param {Object} data - 验证后的数据 + * @returns {Object} 格式化后的数据 + */ + formatData(data) { + const formattedTopics = data.data.map(item => ({ + rank: parseInt(item.rank) || 0, + title: String(item.title || '').trim(), + score: parseInt(item.score) || 0, + scoreDesc: String(item.score_desc || '').trim(), + // 添加一些计算字段 + isTop3: parseInt(item.rank) <= 3, + formattedScore: this.formatScore(item.score), + searchUrl: this.generateSearchUrl(item.title) + })); + + return { + code: data.code, + message: data.message, + data: formattedTopics, + updateTime: new Date().toLocaleString('zh-CN'), + total: formattedTopics.length + }; + } + + /** + * 格式化分数显示 + * @param {number} score - 原始分数 + * @returns {string} 格式化后的分数 + */ + formatScore(score) { + if (!score || isNaN(score)) return '0'; + + if (score >= 10000) { + return (score / 10000).toFixed(1) + 'w'; + } + + return score.toLocaleString(); + } + + /** + * 生成搜索URL + * @param {string} title - 热搜标题 + * @returns {string} 搜索URL + */ + generateSearchUrl(title) { + const encodedTitle = encodeURIComponent(title); + return `https://www.dongchedi.com/search?query=${encodedTitle}`; + } + + /** + * 延迟函数 + * @param {number} ms - 延迟毫秒数 + * @returns {Promise} Promise对象 + */ + delay(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + /** + * 获取API状态 + * @returns {Promise} API状态信息 + */ + async getAPIStatus() { + try { + const startTime = Date.now(); + await this.fetchHotTopics(); + const responseTime = Date.now() - startTime; + + return { + status: 'online', + responseTime: responseTime, + message: 'API服务正常' + }; + } catch (error) { + return { + status: 'offline', + responseTime: null, + message: error.message + }; + } + } +} + +// 导出API实例 +window.CarHotTopicsAPI = CarHotTopicsAPI; \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/app.js b/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/app.js new file mode 100644 index 00000000..9972067a --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/app.js @@ -0,0 +1,313 @@ +/** + * 懂车帝热搜应用主程序 + * 整合API和UI模块,管理应用生命周期 + */ +class CarHotTopicsApp { + constructor() { + this.api = null; + this.ui = null; + this.autoRefreshInterval = null; + this.autoRefreshDelay = 5 * 60 * 1000; // 5分钟自动刷新 + this.isInitialized = false; + + this.init(); + } + + /** + * 初始化应用 + */ + async init() { + try { + console.log('[App] 开始初始化懂车帝热搜应用...'); + + // 等待DOM加载完成 + if (document.readyState === 'loading') { + await new Promise(resolve => { + document.addEventListener('DOMContentLoaded', resolve); + }); + } + + // 检查必需的类是否存在 + if (!window.CarHotTopicsAPI || !window.UIManager) { + throw new Error('缺少必需的模块:CarHotTopicsAPI 或 UIManager'); + } + + // 初始化模块 + this.api = new window.CarHotTopicsAPI(); + this.ui = new window.UIManager(); + + // 检查必需的DOM元素 + this.checkRequiredElements(); + + // 绑定事件 + this.bindEvents(); + + // 首次加载数据 + await this.loadData(); + + // 设置自动刷新 + this.setupAutoRefresh(); + + // 设置页面可见性监听 + this.setupVisibilityListener(); + + this.isInitialized = true; + console.log('[App] 应用初始化完成'); + + } catch (error) { + console.error('[App] 初始化失败:', error); + this.handleInitError(error); + } + } + + /** + * 检查必需的DOM元素 + */ + checkRequiredElements() { + const requiredIds = ['loading', 'error', 'hotList', 'topicsContainer', 'refreshBtn']; + const missingElements = requiredIds.filter(id => !document.getElementById(id)); + + if (missingElements.length > 0) { + throw new Error(`缺少必需的DOM元素: ${missingElements.join(', ')}`); + } + } + + /** + * 绑定事件监听器 + */ + bindEvents() { + // 监听UI触发的刷新事件 + document.addEventListener('refreshData', () => { + this.handleManualRefresh(); + }); + + // 监听网络状态变化 + window.addEventListener('online', () => { + console.log('[App] 网络已连接,尝试刷新数据'); + this.ui.showToast('网络已连接'); + this.loadData(); + }); + + window.addEventListener('offline', () => { + console.log('[App] 网络已断开'); + this.ui.showToast('网络连接已断开'); + }); + + // 监听页面错误 + window.addEventListener('error', (event) => { + console.error('[App] 页面错误:', event.error); + }); + + // 监听未处理的Promise拒绝 + window.addEventListener('unhandledrejection', (event) => { + console.error('[App] 未处理的Promise拒绝:', event.reason); + event.preventDefault(); + }); + } + + /** + * 加载热搜数据 + * @param {boolean} showLoading - 是否显示加载状态 + */ + async loadData(showLoading = true) { + try { + if (showLoading) { + this.ui.showLoading(); + } + + console.log('[App] 开始加载热搜数据...'); + const data = await this.api.fetchHotTopics(); + + console.log('[App] 数据加载成功:', data); + this.ui.showHotList(data); + + // 重置自动刷新计时器 + this.resetAutoRefresh(); + + } catch (error) { + console.error('[App] 数据加载失败:', error); + this.ui.showError(error.message); + + // 如果是网络错误,延迟重试 + if (this.isNetworkError(error)) { + setTimeout(() => { + if (navigator.onLine) { + this.loadData(false); + } + }, 30000); // 30秒后重试 + } + } + } + + /** + * 处理手动刷新 + */ + async handleManualRefresh() { + console.log('[App] 手动刷新数据'); + await this.loadData(); + } + + /** + * 设置自动刷新 + */ + setupAutoRefresh() { + if (this.autoRefreshInterval) { + clearInterval(this.autoRefreshInterval); + } + + this.autoRefreshInterval = setInterval(() => { + if (document.visibilityState === 'visible' && navigator.onLine) { + console.log('[App] 自动刷新数据'); + this.loadData(false); + } + }, this.autoRefreshDelay); + + console.log(`[App] 自动刷新已设置,间隔: ${this.autoRefreshDelay / 1000}秒`); + } + + /** + * 重置自动刷新计时器 + */ + resetAutoRefresh() { + this.setupAutoRefresh(); + } + + /** + * 设置页面可见性监听 + */ + setupVisibilityListener() { + document.addEventListener('visibilitychange', () => { + if (document.visibilityState === 'visible') { + console.log('[App] 页面变为可见'); + + // 检查数据是否需要更新 + const currentData = this.ui.getCurrentData(); + if (currentData) { + const lastUpdate = new Date(currentData.updateTime); + const now = new Date(); + const timeDiff = now - lastUpdate; + + // 如果数据超过3分钟,自动刷新 + if (timeDiff > 3 * 60 * 1000) { + console.log('[App] 数据已过期,自动刷新'); + this.loadData(false); + } + } + } else { + console.log('[App] 页面变为隐藏'); + } + }); + } + + /** + * 判断是否为网络错误 + * @param {Error} error - 错误对象 + * @returns {boolean} 是否为网络错误 + */ + isNetworkError(error) { + const networkErrorMessages = [ + 'fetch', + 'network', + 'timeout', + 'connection', + 'offline' + ]; + + return networkErrorMessages.some(msg => + error.message.toLowerCase().includes(msg) + ); + } + + /** + * 处理初始化错误 + * @param {Error} error - 错误对象 + */ + handleInitError(error) { + // 显示基本错误信息 + const errorContainer = document.getElementById('error'); + if (errorContainer) { + errorContainer.style.display = 'flex'; + const errorMessage = errorContainer.querySelector('.error-message'); + if (errorMessage) { + errorMessage.textContent = `初始化失败: ${error.message}`; + } + } + + // 隐藏加载状态 + const loadingContainer = document.getElementById('loading'); + if (loadingContainer) { + loadingContainer.style.display = 'none'; + } + } + + /** + * 获取应用状态 + * @returns {Object} 应用状态信息 + */ + getStatus() { + return { + isInitialized: this.isInitialized, + hasData: !!this.ui?.getCurrentData(), + autoRefreshEnabled: !!this.autoRefreshInterval, + isOnline: navigator.onLine, + isVisible: document.visibilityState === 'visible' + }; + } + + /** + * 销毁应用 + */ + destroy() { + console.log('[App] 销毁应用'); + + if (this.autoRefreshInterval) { + clearInterval(this.autoRefreshInterval); + this.autoRefreshInterval = null; + } + + if (this.ui) { + this.ui.clearData(); + } + + this.isInitialized = false; + } +} + +// 全局错误处理 +window.addEventListener('error', (event) => { + console.error('[Global] JavaScript错误:', { + message: event.message, + filename: event.filename, + lineno: event.lineno, + colno: event.colno, + error: event.error + }); +}); + +window.addEventListener('unhandledrejection', (event) => { + console.error('[Global] 未处理的Promise拒绝:', event.reason); +}); + +// 应用启动 +let app; + +// 确保在DOM加载完成后启动应用 +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => { + app = new CarHotTopicsApp(); + }); +} else { + app = new CarHotTopicsApp(); +} + +// 导出应用实例(用于调试) +window.CarHotTopicsApp = CarHotTopicsApp; +window.app = app; + +// 调试信息 +console.log('[App] 懂车帝热搜应用脚本已加载'); +console.log('[Debug] 可用的全局对象:', { + CarHotTopicsAPI: !!window.CarHotTopicsAPI, + UIManager: !!window.UIManager, + CarHotTopicsApp: !!window.CarHotTopicsApp +}); \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/background.css b/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/background.css new file mode 100644 index 00000000..4b43a29f --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/background.css @@ -0,0 +1,55 @@ +/* 背景样式文件 */ +body { + background: linear-gradient(135deg, #e8f5e8 0%, #f0f8f0 25%, #f5f9f5 50%, #fafcfa 75%, #ffffff 100%); + background-attachment: fixed; + background-size: 400% 400%; + animation: gradientShift 15s ease infinite; +} + +/* 背景动画 */ +@keyframes gradientShift { + 0% { + background-position: 0% 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0% 50%; + } +} + +/* 容器背景 */ +.container { + background: rgba(255, 255, 255, 0.1); + backdrop-filter: blur(10px); + border-radius: 20px; + margin-top: 20px; + margin-bottom: 20px; + box-shadow: 0 8px 32px rgba(139, 195, 74, 0.1); +} + +/* 移动端背景优化 */ +@media (max-width: 767px) { + body { + background-attachment: scroll; + } + + .container { + margin-top: 10px; + margin-bottom: 10px; + border-radius: 16px; + } +} + +/* 深色模式支持 */ +@media (prefers-color-scheme: dark) { + body { + background: linear-gradient(135deg, #1a2e1a 0%, #2d4a2d 25%, #3a5a3a 50%, #4a6a4a 75%, #5a7a5a 100%); + } + + .container { + background: rgba(0, 0, 0, 0.2); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); + } +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/index.html b/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/index.html new file mode 100644 index 00000000..6c84eae6 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/index.html @@ -0,0 +1,72 @@ + + + + + + + + 懂车帝热搜榜单 + + + + + +
+ +
+ + +
+ + +
+ +
+
+

正在加载热搜数据...

+
+ + + + + + +
+ + +
+ +
+
+ + +
+ + + + + + \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/styles.css b/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/styles.css new file mode 100644 index 00000000..b5fc8011 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/styles.css @@ -0,0 +1,532 @@ +/* 全局样式重置 */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; + line-height: 1.6; + color: #333; + min-height: 100vh; + overflow-x: hidden; +} + +/* 容器布局 */ +.container { + max-width: 1200px; + margin: 0 auto; + min-height: 100vh; + display: flex; + flex-direction: column; + padding: 0 16px; +} + +/* 头部样式 */ +.header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 20px 0; + border-bottom: 1px solid rgba(139, 195, 74, 0.2); + margin-bottom: 20px; +} + +.logo { + display: flex; + align-items: center; + gap: 12px; +} + +.logo i { + font-size: 28px; + color: #8bc34a; + background: linear-gradient(135deg, #a5d6a7, #81c784); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.logo h1 { + font-size: 24px; + font-weight: 600; + color: #2e7d32; + margin: 0; +} + +.refresh-btn { + display: flex; + align-items: center; + gap: 8px; + padding: 10px 16px; + background: linear-gradient(135deg, #a5d6a7, #81c784); + color: white; + border: none; + border-radius: 20px; + cursor: pointer; + font-size: 14px; + font-weight: 500; + transition: all 0.3s ease; + box-shadow: 0 2px 8px rgba(139, 195, 74, 0.3); +} + +.refresh-btn:hover { + background: linear-gradient(135deg, #81c784, #66bb6a); + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(139, 195, 74, 0.4); +} + +.refresh-btn:active { + transform: translateY(0); +} + +.refresh-btn i { + font-size: 14px; +} + +.refresh-btn.loading i { + animation: spin 1s linear infinite; +} + +/* 主内容区域 */ +.main-content { + flex: 1; + position: relative; +} + +/* 加载状态 */ +.loading { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 60px 20px; + text-align: center; +} + +.loading-spinner { + width: 40px; + height: 40px; + border: 3px solid rgba(139, 195, 74, 0.2); + border-top: 3px solid #8bc34a; + border-radius: 50%; + animation: spin 1s linear infinite; + margin-bottom: 16px; +} + +.loading p { + color: #666; + font-size: 16px; +} + +/* 错误状态 */ +.error { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 60px 20px; + text-align: center; +} + +.error-icon i { + font-size: 48px; + color: #ff7043; + margin-bottom: 16px; +} + +.error-message { + color: #666; + font-size: 16px; + margin-bottom: 20px; +} + +.retry-btn { + padding: 10px 20px; + background: linear-gradient(135deg, #a5d6a7, #81c784); + color: white; + border: none; + border-radius: 20px; + cursor: pointer; + font-size: 14px; + transition: all 0.3s ease; +} + +.retry-btn:hover { + background: linear-gradient(135deg, #81c784, #66bb6a); +} + +/* 热搜列表 */ +.hot-list { + animation: fadeIn 0.5s ease-in; +} + +.list-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; + padding-bottom: 12px; + border-bottom: 2px solid rgba(139, 195, 74, 0.2); +} + +.list-header h2 { + font-size: 20px; + font-weight: 600; + color: #2e7d32; + margin: 0; +} + +.update-time { + font-size: 12px; + color: #666; + background: rgba(139, 195, 74, 0.1); + padding: 4px 8px; + border-radius: 12px; +} + +.topics-container { + display: grid; + gap: 12px; +} + +/* 热搜项目 */ +.topic-item { + background: white; + border-radius: 12px; + padding: 16px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + border: 1px solid rgba(139, 195, 74, 0.1); + transition: all 0.3s ease; + cursor: pointer; + position: relative; + overflow: hidden; +} + +.topic-item:hover { + transform: translateY(-2px); + box-shadow: 0 4px 16px rgba(139, 195, 74, 0.15); + border-color: rgba(139, 195, 74, 0.3); +} + +.topic-item::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 4px; + height: 100%; + background: linear-gradient(135deg, #a5d6a7, #81c784); + opacity: 0; + transition: opacity 0.3s ease; +} + +.topic-item:hover::before { + opacity: 1; +} + +.topic-header { + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 8px; +} + +.rank-badge { + display: flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + border-radius: 50%; + font-size: 12px; + font-weight: 600; + color: white; + flex-shrink: 0; +} + +.rank-badge.top-3 { + background: linear-gradient(135deg, #ffb74d, #ff9800); + box-shadow: 0 2px 6px rgba(255, 152, 0, 0.3); +} + +.rank-badge.normal { + background: linear-gradient(135deg, #a5d6a7, #81c784); + box-shadow: 0 2px 6px rgba(139, 195, 74, 0.3); +} + +.topic-title { + font-size: 16px; + font-weight: 500; + color: #333; + line-height: 1.4; + flex: 1; + word-break: break-word; +} + +.topic-footer { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 12px; + padding-top: 8px; + border-top: 1px solid rgba(139, 195, 74, 0.1); +} + +.topic-score { + font-size: 14px; + font-weight: 600; + color: #8bc34a; +} + +.topic-actions { + display: flex; + gap: 8px; +} + +.action-btn { + padding: 4px 8px; + background: rgba(139, 195, 74, 0.1); + color: #8bc34a; + border: none; + border-radius: 6px; + cursor: pointer; + font-size: 12px; + transition: all 0.3s ease; +} + +.action-btn:hover { + background: rgba(139, 195, 74, 0.2); +} + +/* 底部样式 */ +.footer { + margin-top: 40px; + padding: 20px 0; + border-top: 1px solid rgba(139, 195, 74, 0.2); + text-align: center; +} + +.footer-content p { + margin: 4px 0; + font-size: 12px; + color: #666; +} + +.data-source { + font-weight: 500; +} + +/* 提示消息 */ +.toast { + position: fixed; + top: 20px; + left: 50%; + transform: translateX(-50%); + background: rgba(46, 125, 50, 0.9); + color: white; + padding: 12px 20px; + border-radius: 20px; + font-size: 14px; + z-index: 1000; + opacity: 0; + visibility: hidden; + transition: all 0.3s ease; + backdrop-filter: blur(10px); +} + +.toast.show { + opacity: 1; + visibility: visible; +} + +/* 动画效果 */ +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +@keyframes fadeIn { + 0% { + opacity: 0; + transform: translateY(20px); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} + +/* 平板端适配 */ +@media (min-width: 768px) and (max-width: 1024px) { + .container { + padding: 0 24px; + } + + .topics-container { + grid-template-columns: repeat(2, 1fr); + gap: 16px; + } + + .topic-item { + padding: 18px; + } + + .logo h1 { + font-size: 26px; + } + + .topic-title { + font-size: 17px; + } +} + +/* 桌面端适配 */ +@media (min-width: 1025px) { + .container { + padding: 0 32px; + } + + .header { + padding: 24px 0; + } + + .topics-container { + grid-template-columns: repeat(3, 1fr); + gap: 20px; + } + + .topic-item { + padding: 20px; + } + + .logo h1 { + font-size: 28px; + } + + .topic-title { + font-size: 18px; + } + + .refresh-btn { + padding: 12px 20px; + font-size: 15px; + } +} + +/* 移动端优化 */ +@media (max-width: 767px) { + .container { + padding: 0 12px; + } + + .header { + padding: 16px 0; + margin-bottom: 16px; + } + + .logo h1 { + font-size: 20px; + } + + .logo i { + font-size: 24px; + } + + .refresh-btn { + padding: 8px 12px; + font-size: 13px; + } + + .refresh-btn span { + display: none; + } + + .topics-container { + grid-template-columns: 1fr; + gap: 10px; + } + + .topic-item { + padding: 14px; + } + + .topic-title { + font-size: 15px; + line-height: 1.3; + } + + .rank-badge { + width: 22px; + height: 22px; + font-size: 11px; + } + + .topic-score { + font-size: 13px; + } + + .action-btn { + padding: 3px 6px; + font-size: 11px; + } + + .list-header h2 { + font-size: 18px; + } + + .update-time { + font-size: 11px; + } + + .footer { + margin-top: 30px; + padding: 16px 0; + } + + .toast { + left: 12px; + right: 12px; + transform: none; + border-radius: 12px; + } +} + +/* 超小屏幕优化 */ +@media (max-width: 360px) { + .container { + padding: 0 8px; + } + + .topic-item { + padding: 12px; + } + + .topic-title { + font-size: 14px; + } + + .logo h1 { + font-size: 18px; + } +} + +/* 滚动条样式 */ +::-webkit-scrollbar { + width: 6px; +} + +::-webkit-scrollbar-track { + background: rgba(139, 195, 74, 0.1); + border-radius: 3px; +} + +::-webkit-scrollbar-thumb { + background: rgba(139, 195, 74, 0.5); + border-radius: 3px; +} + +::-webkit-scrollbar-thumb:hover { + background: rgba(139, 195, 74, 0.7); +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/ui.js b/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/ui.js new file mode 100644 index 00000000..bb151216 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/ui.js @@ -0,0 +1,410 @@ +/** + * UI管理模块 + * 负责页面渲染、交互和状态管理 + */ +class UIManager { + constructor() { + this.elements = {}; + this.isLoading = false; + this.currentData = null; + this.touchStartY = 0; + this.pullThreshold = 80; + this.isPulling = false; + + this.initElements(); + this.bindEvents(); + } + + /** + * 初始化DOM元素引用 + */ + initElements() { + this.elements = { + loading: document.getElementById('loading'), + error: document.getElementById('error'), + hotList: document.getElementById('hotList'), + topicsContainer: document.getElementById('topicsContainer'), + refreshBtn: document.getElementById('refreshBtn'), + updateTime: document.getElementById('updateTime'), + toast: document.getElementById('toast') + }; + + // 检查必需元素 + const missingElements = Object.entries(this.elements) + .filter(([key, element]) => !element) + .map(([key]) => key); + + if (missingElements.length > 0) { + console.error('[UI] 缺少必需的DOM元素:', missingElements); + } + } + + /** + * 绑定事件监听器 + */ + bindEvents() { + // 刷新按钮点击事件 + if (this.elements.refreshBtn) { + this.elements.refreshBtn.addEventListener('click', () => { + this.handleRefresh(); + }); + } + + // 键盘快捷键 + document.addEventListener('keydown', (e) => { + if (e.key === 'F5' || (e.ctrlKey && e.key === 'r')) { + e.preventDefault(); + this.handleRefresh(); + } + }); + + // 移动端下拉刷新 + this.initPullToRefresh(); + + // 页面可见性变化 + document.addEventListener('visibilitychange', () => { + if (!document.hidden && this.currentData) { + // 页面重新可见时检查数据是否过期(5分钟) + const lastUpdate = new Date(this.currentData.updateTime); + const now = new Date(); + if (now - lastUpdate > 5 * 60 * 1000) { + this.handleRefresh(); + } + } + }); + } + + /** + * 初始化下拉刷新功能 + */ + initPullToRefresh() { + let startY = 0; + let currentY = 0; + let pullDistance = 0; + + document.addEventListener('touchstart', (e) => { + if (window.scrollY === 0) { + startY = e.touches[0].clientY; + this.isPulling = true; + } + }, { passive: true }); + + document.addEventListener('touchmove', (e) => { + if (!this.isPulling || this.isLoading) return; + + currentY = e.touches[0].clientY; + pullDistance = currentY - startY; + + if (pullDistance > 0 && window.scrollY === 0) { + e.preventDefault(); + + // 添加视觉反馈 + const progress = Math.min(pullDistance / this.pullThreshold, 1); + document.body.style.transform = `translateY(${pullDistance * 0.3}px)`; + document.body.style.opacity = 1 - progress * 0.1; + } + }, { passive: false }); + + document.addEventListener('touchend', () => { + if (this.isPulling) { + document.body.style.transform = ''; + document.body.style.opacity = ''; + + if (pullDistance > this.pullThreshold && !this.isLoading) { + this.handleRefresh(); + } + + this.isPulling = false; + pullDistance = 0; + } + }); + } + + /** + * 处理刷新操作 + */ + async handleRefresh() { + if (this.isLoading) return; + + this.showToast('正在刷新数据...'); + + // 触发自定义刷新事件 + const refreshEvent = new CustomEvent('refreshData'); + document.dispatchEvent(refreshEvent); + } + + /** + * 显示加载状态 + */ + showLoading() { + this.isLoading = true; + this.hideAllStates(); + if (this.elements.loading) { + this.elements.loading.style.display = 'flex'; + } + + // 刷新按钮加载状态 + if (this.elements.refreshBtn) { + this.elements.refreshBtn.classList.add('loading'); + this.elements.refreshBtn.disabled = true; + } + } + + /** + * 显示错误状态 + * @param {string} message - 错误消息 + */ + showError(message = '加载失败,请稍后重试') { + this.isLoading = false; + this.hideAllStates(); + + if (this.elements.error) { + this.elements.error.style.display = 'flex'; + const errorMessage = this.elements.error.querySelector('.error-message'); + if (errorMessage) { + errorMessage.textContent = message; + } + } + + this.resetRefreshButton(); + } + + /** + * 显示热搜列表 + * @param {Object} data - 热搜数据 + */ + showHotList(data) { + this.isLoading = false; + this.currentData = data; + this.hideAllStates(); + + if (this.elements.hotList) { + this.elements.hotList.style.display = 'block'; + } + + this.renderTopics(data.data); + this.updateTime(data.updateTime); + this.resetRefreshButton(); + + this.showToast(`已更新 ${data.total} 条热搜数据`); + } + + /** + * 隐藏所有状态 + */ + hideAllStates() { + ['loading', 'error', 'hotList'].forEach(state => { + if (this.elements[state]) { + this.elements[state].style.display = 'none'; + } + }); + } + + /** + * 重置刷新按钮状态 + */ + resetRefreshButton() { + if (this.elements.refreshBtn) { + this.elements.refreshBtn.classList.remove('loading'); + this.elements.refreshBtn.disabled = false; + } + } + + /** + * 渲染热搜话题列表 + * @param {Array} topics - 话题数组 + */ + renderTopics(topics) { + if (!this.elements.topicsContainer) return; + + this.elements.topicsContainer.innerHTML = ''; + + topics.forEach((topic, index) => { + const topicElement = this.createTopicElement(topic, index); + this.elements.topicsContainer.appendChild(topicElement); + }); + } + + /** + * 创建单个话题元素 + * @param {Object} topic - 话题数据 + * @param {number} index - 索引 + * @returns {HTMLElement} 话题元素 + */ + createTopicElement(topic, index) { + const item = document.createElement('div'); + item.className = 'topic-item'; + item.style.animationDelay = `${index * 0.1}s`; + + item.innerHTML = ` +
+
+ ${topic.rank} +
+
${this.escapeHtml(topic.title)}
+
+ + `; + + this.bindTopicEvents(item, topic); + return item; + } + + /** + * 绑定话题元素事件 + * @param {HTMLElement} element - 话题元素 + * @param {Object} topic - 话题数据 + */ + bindTopicEvents(element, topic) { + // 点击整个项目跳转搜索 + element.addEventListener('click', (e) => { + if (!e.target.closest('.action-btn')) { + window.open(topic.searchUrl, '_blank'); + } + }); + + // 复制按钮 + const copyBtn = element.querySelector('.copy-btn'); + if (copyBtn) { + copyBtn.addEventListener('click', (e) => { + e.stopPropagation(); + this.copyToClipboard(topic.title); + }); + } + + // 搜索按钮 + const searchBtn = element.querySelector('.search-btn'); + if (searchBtn) { + searchBtn.addEventListener('click', (e) => { + e.stopPropagation(); + window.open(topic.searchUrl, '_blank'); + }); + } + + // 长按显示详情 + let longPressTimer; + element.addEventListener('touchstart', () => { + longPressTimer = setTimeout(() => { + this.showTopicDetails(topic); + }, 800); + }); + + element.addEventListener('touchend', () => { + clearTimeout(longPressTimer); + }); + + element.addEventListener('touchmove', () => { + clearTimeout(longPressTimer); + }); + } + + /** + * 显示话题详情 + * @param {Object} topic - 话题数据 + */ + showTopicDetails(topic) { + const details = ` + 标题: ${topic.title} + 排名: 第${topic.rank}名 + 热度: ${topic.scoreDesc} + 原始分数: ${topic.score.toLocaleString()} + `; + + this.showToast(details, 3000); + } + + /** + * 复制文本到剪贴板 + * @param {string} text - 要复制的文本 + */ + async copyToClipboard(text) { + try { + if (navigator.clipboard && window.isSecureContext) { + await navigator.clipboard.writeText(text); + } else { + // 降级方案 + const textArea = document.createElement('textarea'); + textArea.value = text; + textArea.style.position = 'fixed'; + textArea.style.opacity = '0'; + document.body.appendChild(textArea); + textArea.select(); + document.execCommand('copy'); + document.body.removeChild(textArea); + } + + this.showToast('已复制到剪贴板'); + } catch (error) { + console.error('[UI] 复制失败:', error); + this.showToast('复制失败'); + } + } + + /** + * 更新时间显示 + * @param {string} time - 更新时间 + */ + updateTime(time) { + if (this.elements.updateTime) { + this.elements.updateTime.textContent = `更新时间: ${time}`; + } + } + + /** + * 显示提示消息 + * @param {string} message - 消息内容 + * @param {number} duration - 显示时长(毫秒) + */ + showToast(message, duration = 2000) { + if (!this.elements.toast) return; + + this.elements.toast.textContent = message; + this.elements.toast.classList.add('show'); + + setTimeout(() => { + this.elements.toast.classList.remove('show'); + }, duration); + } + + /** + * HTML转义 + * @param {string} text - 原始文本 + * @returns {string} 转义后的文本 + */ + escapeHtml(text) { + const div = document.createElement('div'); + div.textContent = text; + return div.innerHTML; + } + + /** + * 获取当前数据 + * @returns {Object|null} 当前数据 + */ + getCurrentData() { + return this.currentData; + } + + /** + * 清除当前数据 + */ + clearData() { + this.currentData = null; + if (this.elements.topicsContainer) { + this.elements.topicsContainer.innerHTML = ''; + } + } +} + +// 导出UI管理器 +window.UIManager = UIManager; \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/返回接口.json b/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/返回接口.json new file mode 100644 index 00000000..441f0095 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/返回接口.json @@ -0,0 +1,66 @@ +{ + "code": 200, + "message": "获取成功。数据来自官方/权威源头,以确保稳定与实时。开源地址 https://github.com/vikiboss/60s,反馈群 595941841", + "data": [ + { + "rank": 1, + "title": "吉利银河星耀6将于9月5日发布", + "score": 846099, + "score_desc": "84.6w" + }, + { + "rank": 2, + "title": "销售称Model Y L日均订单近万辆", + "score": 602350, + "score_desc": "60.2w" + }, + { + "rank": 3, + "title": "极氪9X将于9月底上市", + "score": 241114, + "score_desc": "24.1w" + }, + { + "rank": 4, + "title": "比亚迪“全家福”亮相齐鲁秋季车展", + "score": 239586, + "score_desc": "24.0w" + }, + { + "rank": 5, + "title": "新一代宝马X5内饰曝光", + "score": 209847, + "score_desc": "21.0w" + }, + { + "rank": 6, + "title": "LOL前职业选手PDD喜提理想MEGA", + "score": 204628, + "score_desc": "20.5w" + }, + { + "rank": 7, + "title": "零跑Lafa5伪装车曝光", + "score": 143127, + "score_desc": "14.3w" + }, + { + "rank": 8, + "title": "方程豹钛7将于9月9日上市", + "score": 135759, + "score_desc": "13.6w" + }, + { + "rank": 9, + "title": "零跑9月购车政策", + "score": 94419, + "score_desc": "9.4w" + }, + { + "rank": 10, + "title": "捷途X70L将于9月10日预售", + "score": 74292, + "score_desc": "7.4w" + } + ] +} \ No newline at end of file diff --git a/frontend/public/60sapi/热搜榜单/抖音热搜榜/css/background.css b/InfoGenie-frontend/public/60sapi/热搜榜单/抖音热搜榜/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/抖音热搜榜/css/background.css rename to InfoGenie-frontend/public/60sapi/热搜榜单/抖音热搜榜/css/background.css diff --git a/frontend/public/60sapi/热搜榜单/抖音热搜榜/css/style.css b/InfoGenie-frontend/public/60sapi/热搜榜单/抖音热搜榜/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/抖音热搜榜/css/style.css rename to InfoGenie-frontend/public/60sapi/热搜榜单/抖音热搜榜/css/style.css diff --git a/frontend/public/60sapi/热搜榜单/抖音热搜榜/index.html b/InfoGenie-frontend/public/60sapi/热搜榜单/抖音热搜榜/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/抖音热搜榜/index.html rename to InfoGenie-frontend/public/60sapi/热搜榜单/抖音热搜榜/index.html diff --git a/frontend/public/60sapi/热搜榜单/抖音热搜榜/js/script.js b/InfoGenie-frontend/public/60sapi/热搜榜单/抖音热搜榜/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/抖音热搜榜/js/script.js rename to InfoGenie-frontend/public/60sapi/热搜榜单/抖音热搜榜/js/script.js diff --git a/frontend/public/60sapi/热搜榜单/抖音热搜榜/接口集合.json b/InfoGenie-frontend/public/60sapi/热搜榜单/抖音热搜榜/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/抖音热搜榜/接口集合.json rename to InfoGenie-frontend/public/60sapi/热搜榜单/抖音热搜榜/接口集合.json diff --git a/frontend/public/60sapi/热搜榜单/抖音热搜榜/返回接口.json b/InfoGenie-frontend/public/60sapi/热搜榜单/抖音热搜榜/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/抖音热搜榜/返回接口.json rename to InfoGenie-frontend/public/60sapi/热搜榜单/抖音热搜榜/返回接口.json diff --git a/frontend/public/60sapi/热搜榜单/猫眼票房排行榜/css/style.css b/InfoGenie-frontend/public/60sapi/热搜榜单/猫眼票房排行榜/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/猫眼票房排行榜/css/style.css rename to InfoGenie-frontend/public/60sapi/热搜榜单/猫眼票房排行榜/css/style.css diff --git a/frontend/public/60sapi/热搜榜单/猫眼票房排行榜/index.html b/InfoGenie-frontend/public/60sapi/热搜榜单/猫眼票房排行榜/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/猫眼票房排行榜/index.html rename to InfoGenie-frontend/public/60sapi/热搜榜单/猫眼票房排行榜/index.html diff --git a/frontend/public/60sapi/热搜榜单/猫眼票房排行榜/js/script.js b/InfoGenie-frontend/public/60sapi/热搜榜单/猫眼票房排行榜/js/script.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/猫眼票房排行榜/js/script.js rename to InfoGenie-frontend/public/60sapi/热搜榜单/猫眼票房排行榜/js/script.js diff --git a/frontend/public/60sapi/热搜榜单/猫眼票房排行榜/接口集合.json b/InfoGenie-frontend/public/60sapi/热搜榜单/猫眼票房排行榜/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/猫眼票房排行榜/接口集合.json rename to InfoGenie-frontend/public/60sapi/热搜榜单/猫眼票房排行榜/接口集合.json diff --git a/frontend/public/60sapi/热搜榜单/猫眼票房排行榜/返回接口.json b/InfoGenie-frontend/public/60sapi/热搜榜单/猫眼票房排行榜/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/猫眼票房排行榜/返回接口.json rename to InfoGenie-frontend/public/60sapi/热搜榜单/猫眼票房排行榜/返回接口.json diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/百度实时热搜/background.css b/InfoGenie-frontend/public/60sapi/热搜榜单/百度实时热搜/background.css new file mode 100644 index 00000000..7be1cfe9 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/百度实时热搜/background.css @@ -0,0 +1,196 @@ +/* 页面主背景 */ +body { + background: linear-gradient(135deg, #f8fffe 0%, #e8f5e8 50%, #d4f1d4 100%); + background-attachment: fixed; + position: relative; +} + +/* 背景装饰元素 */ +body::before { + content: ''; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-image: + radial-gradient(circle at 20% 80%, rgba(39, 174, 96, 0.05) 0%, transparent 50%), + radial-gradient(circle at 80% 20%, rgba(46, 204, 113, 0.05) 0%, transparent 50%), + radial-gradient(circle at 40% 40%, rgba(168, 230, 207, 0.08) 0%, transparent 50%); + pointer-events: none; + z-index: -1; +} + +/* 容器背景 */ +.container { + background: rgba(255, 255, 255, 0.7); + backdrop-filter: blur(10px); + border-radius: 16px; + box-shadow: 0 8px 32px rgba(39, 174, 96, 0.1); + margin-top: 20px; + margin-bottom: 20px; +} + +/* 头部背景 */ +.header { + background: linear-gradient(135deg, rgba(39, 174, 96, 0.05) 0%, rgba(168, 230, 207, 0.05) 100%); + border-radius: 16px 16px 0 0; + position: relative; + overflow: hidden; +} + +.header::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: + radial-gradient(circle at 30% 20%, rgba(39, 174, 96, 0.1) 0%, transparent 40%), + radial-gradient(circle at 70% 80%, rgba(46, 204, 113, 0.08) 0%, transparent 40%); + pointer-events: none; +} + +/* 热搜项目背景 */ +.hot-item { + background: rgba(255, 255, 255, 0.9); + backdrop-filter: blur(8px); + position: relative; + overflow: hidden; +} + +.hot-item::after { + content: ''; + position: absolute; + top: 0; + right: 0; + width: 60px; + height: 100%; + background: linear-gradient(90deg, transparent 0%, rgba(39, 174, 96, 0.02) 100%); + pointer-events: none; +} + +/* 前三名特殊背景效果 */ +.hot-item:nth-child(1) { + background: linear-gradient(135deg, rgba(231, 76, 60, 0.05) 0%, rgba(255, 255, 255, 0.95) 100%); +} + +.hot-item:nth-child(2) { + background: linear-gradient(135deg, rgba(243, 156, 18, 0.05) 0%, rgba(255, 255, 255, 0.95) 100%); +} + +.hot-item:nth-child(3) { + background: linear-gradient(135deg, rgba(52, 152, 219, 0.05) 0%, rgba(255, 255, 255, 0.95) 100%); +} + +/* 加载状态背景 */ +.loading { + background: rgba(255, 255, 255, 0.8); + backdrop-filter: blur(8px); + border-radius: 12px; + margin: 20px; +} + +/* 错误信息背景 */ +.error-message { + background: linear-gradient(135deg, rgba(231, 76, 60, 0.05) 0%, rgba(255, 255, 255, 0.9) 100%); + backdrop-filter: blur(8px); + border-radius: 12px; + border: 1px solid rgba(231, 76, 60, 0.1); + margin: 20px; +} + +/* 底部背景 */ +.footer { + background: linear-gradient(135deg, rgba(39, 174, 96, 0.03) 0%, rgba(168, 230, 207, 0.03) 100%); + border-radius: 0 0 16px 16px; + position: relative; +} + +.footer::before { + content: ''; + position: absolute; + top: 0; + left: 50%; + transform: translateX(-50%); + width: 60px; + height: 1px; + background: linear-gradient(90deg, transparent 0%, rgba(39, 174, 96, 0.3) 50%, transparent 100%); +} + +/* 响应式背景调整 */ +@media (max-width: 768px) { + .container { + margin-top: 10px; + margin-bottom: 10px; + border-radius: 12px; + } + + .header { + border-radius: 12px 12px 0 0; + } + + .footer { + border-radius: 0 0 12px 12px; + } + + body::before { + background-image: + radial-gradient(circle at 20% 80%, rgba(39, 174, 96, 0.03) 0%, transparent 40%), + radial-gradient(circle at 80% 20%, rgba(46, 204, 113, 0.03) 0%, transparent 40%); + } +} + +@media (min-width: 1025px) { + .container { + margin-top: 40px; + margin-bottom: 40px; + } + + body::before { + background-image: + radial-gradient(circle at 15% 85%, rgba(39, 174, 96, 0.06) 0%, transparent 60%), + radial-gradient(circle at 85% 15%, rgba(46, 204, 113, 0.06) 0%, transparent 60%), + radial-gradient(circle at 50% 50%, rgba(168, 230, 207, 0.04) 0%, transparent 70%); + } +} + +/* 动画效果 */ +@keyframes backgroundShift { + 0% { + background-position: 0% 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0% 50%; + } +} + +/* 悬浮时的背景变化 */ +.hot-item:hover { + background: rgba(255, 255, 255, 0.95); +} + +.hot-item:hover::after { + background: linear-gradient(90deg, transparent 0%, rgba(39, 174, 96, 0.05) 100%); +} + +/* 排名背景渐变 */ +.rank { + position: relative; + overflow: hidden; +} + +.rank::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 0%, transparent 100%); + pointer-events: none; +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/百度实时热搜/index.html b/InfoGenie-frontend/public/60sapi/热搜榜单/百度实时热搜/index.html new file mode 100644 index 00000000..41d8157f --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/百度实时热搜/index.html @@ -0,0 +1,40 @@ + + + + + + 百度实时热搜榜单 + + + + +
+
+

百度实时热搜榜单

+

实时热门搜索,掌握网络脉搏

+
+ +
+
+
+

正在加载热搜数据...

+
+ + + + +
+ +
+

+
+
+ + + + \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/百度实时热搜/script.js b/InfoGenie-frontend/public/60sapi/热搜榜单/百度实时热搜/script.js new file mode 100644 index 00000000..049f2d9b --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/百度实时热搜/script.js @@ -0,0 +1,196 @@ +// DOM元素获取 +const loadingElement = document.getElementById('loading'); +const errorElement = document.getElementById('error'); +const hotListElement = document.getElementById('hotList'); +const updateTimeElement = document.getElementById('updateTime'); + +// 页面加载完成后初始化 +document.addEventListener('DOMContentLoaded', function() { + loadData(); + + // 每5分钟自动刷新数据 + setInterval(loadData, 5 * 60 * 1000); + + // 监听页面可见性变化,页面重新可见时刷新数据 + document.addEventListener('visibilitychange', function() { + if (!document.hidden) { + loadData(); + } + }); + + // 监听网络状态变化 + window.addEventListener('online', loadData); +}); + +// 加载数据函数 +async function loadData() { + try { + showLoading(); + + // 调用百度实时热搜API + const response = await fetch('https://60s.api.shumengya.top/v2/baidu/realtime'); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + + if (data.code === 200 && data.data) { + renderHotList(data.data); + updateTime(); + hideLoading(); + } else { + throw new Error(data.message || '数据格式错误'); + } + + } catch (error) { + console.error('加载数据失败:', error); + showError(); + } +} + +// 渲染热搜列表 +function renderHotList(hotData) { + if (!hotData || !Array.isArray(hotData)) { + showError(); + return; + } + + const listHTML = hotData.map((item, index) => { + const rank = index + 1; + const rankClass = rank <= 3 ? (rank === 1 ? 'top1' : 'top3') : ''; + + // 处理封面图片 + const coverImg = item.pic ? + `${item.title}` : + ''; + + // 处理描述信息 + const description = item.desc || ''; + + // 处理热度值 + const hotValue = item.hot || ''; + + // 处理链接 + const linkUrl = item.url || '#'; + + return ` +
+
${rank}
+ ${coverImg} +
+
+

${item.title || '无标题'}

+
+ ${description ? `

${description}

` : ''} + +
+
+ `; + }).join(''); + + hotListElement.innerHTML = listHTML; + hotListElement.style.display = 'block'; +} + +// 格式化热度值 +function formatHotValue(value) { + if (!value) return ''; + + // 如果是数字,进行格式化 + if (typeof value === 'number') { + if (value >= 10000) { + return (value / 10000).toFixed(1) + '万'; + } + return value.toString(); + } + + // 如果是字符串,直接返回 + return value.toString(); +} + +// 打开链接 +function openLink(url) { + if (url && url !== '#') { + window.open(url, '_blank'); + } +} + +// 显示加载状态 +function showLoading() { + loadingElement.style.display = 'block'; + errorElement.style.display = 'none'; + hotListElement.style.display = 'none'; +} + +// 隐藏加载状态 +function hideLoading() { + loadingElement.style.display = 'none'; +} + +// 显示错误信息 +function showError() { + loadingElement.style.display = 'none'; + errorElement.style.display = 'block'; + hotListElement.style.display = 'none'; +} + +// 更新时间显示 +function updateTime() { + const now = new Date(); + const timeString = now.toLocaleString('zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + }); + updateTimeElement.textContent = `最后更新时间: ${timeString}`; +} + +// 重试加载数据 +function retryLoad() { + loadData(); +} + +// 页面滚动优化 +let ticking = false; + +function updateScrollPosition() { + // 可以在这里添加滚动相关的优化逻辑 + ticking = false; +} + +window.addEventListener('scroll', function() { + if (!ticking) { + requestAnimationFrame(updateScrollPosition); + ticking = true; + } +}); + +// 错误处理和日志记录 +window.addEventListener('error', function(e) { + console.error('页面错误:', e.error); +}); + +window.addEventListener('unhandledrejection', function(e) { + console.error('未处理的Promise拒绝:', e.reason); +}); + +// 性能监控 +if ('performance' in window) { + window.addEventListener('load', function() { + setTimeout(function() { + const perfData = performance.timing; + const loadTime = perfData.loadEventEnd - perfData.navigationStart; + console.log('页面加载时间:', loadTime + 'ms'); + }, 0); + }); +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/百度实时热搜/styles.css b/InfoGenie-frontend/public/60sapi/热搜榜单/百度实时热搜/styles.css new file mode 100644 index 00000000..766cde4e --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/百度实时热搜/styles.css @@ -0,0 +1,371 @@ +/* 基础样式重置 */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; + line-height: 1.6; + color: #2c3e50; + overflow-x: hidden; +} + +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 16px; + min-height: 100vh; + display: flex; + flex-direction: column; +} + +/* 头部样式 */ +.header { + text-align: center; + padding: 24px 0; + border-bottom: 2px solid #a8e6cf; + margin-bottom: 24px; +} + +.title { + font-size: 28px; + font-weight: 700; + color: #27ae60; + margin-bottom: 8px; + text-shadow: 0 2px 4px rgba(39, 174, 96, 0.1); +} + +.subtitle { + font-size: 14px; + color: #7f8c8d; + font-weight: 400; +} + +/* 主内容区域 */ +.main-content { + flex: 1; + position: relative; +} + +/* 加载状态 */ +.loading { + text-align: center; + padding: 60px 20px; + color: #27ae60; +} + +.loading-spinner { + width: 40px; + height: 40px; + border: 3px solid #a8e6cf; + border-top: 3px solid #27ae60; + border-radius: 50%; + animation: spin 1s linear infinite; + margin: 0 auto 16px; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* 错误信息 */ +.error-message { + text-align: center; + padding: 40px 20px; + color: #e74c3c; +} + +.retry-btn { + background: #27ae60; + color: white; + border: none; + padding: 10px 20px; + border-radius: 20px; + cursor: pointer; + font-size: 14px; + margin-top: 16px; + transition: background 0.3s ease; +} + +.retry-btn:hover { + background: #219a52; +} + +/* 热搜列表 */ +.hot-list { + display: grid; + gap: 16px; +} + +.hot-item { + background: #ffffff; + border: 1px solid #e8f5e8; + border-radius: 12px; + padding: 16px; + transition: all 0.3s ease; + box-shadow: 0 2px 8px rgba(39, 174, 96, 0.08); + position: relative; + overflow: hidden; + display: flex; + gap: 12px; + cursor: pointer; +} + +.hot-item:hover { + transform: translateY(-2px); + box-shadow: 0 4px 16px rgba(39, 174, 96, 0.15); + border-color: #a8e6cf; +} + +.hot-item::before { + content: ''; + position: absolute; + left: 0; + top: 0; + width: 4px; + height: 100%; + background: linear-gradient(to bottom, #27ae60, #a8e6cf); +} + +/* 排名样式 */ +.rank { + background: linear-gradient(135deg, #27ae60, #2ecc71); + color: white; + width: 32px; + height: 32px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + font-size: 14px; + flex-shrink: 0; + margin-top: 4px; +} + +.rank.top3 { + background: linear-gradient(135deg, #f39c12, #e67e22); +} + +.rank.top1 { + background: linear-gradient(135deg, #e74c3c, #c0392b); +} + +/* 封面图片 */ +.item-cover { + width: 80px; + height: 60px; + border-radius: 8px; + object-fit: cover; + flex-shrink: 0; + border: 1px solid #e8f5e8; +} + +/* 内容区域 */ +.item-content { + flex: 1; + display: flex; + flex-direction: column; + justify-content: space-between; + min-height: 60px; +} + +.item-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + margin-bottom: 8px; +} + +.item-title { + font-size: 16px; + font-weight: 600; + color: #2c3e50; + line-height: 1.4; + margin-bottom: 4px; + transition: color 0.3s ease; + flex: 1; +} + +.item-title:hover { + color: #27ae60; +} + +.item-desc { + font-size: 13px; + color: #7f8c8d; + line-height: 1.3; + margin-bottom: 8px; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.item-footer { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; +} + +.item-score { + font-size: 14px; + color: #27ae60; + font-weight: 600; +} + +.item-type { + display: flex; + align-items: center; + gap: 4px; +} + +.type-icon { + width: 16px; + height: 16px; + object-fit: contain; +} + +.type-text { + font-size: 12px; + padding: 2px 8px; + border-radius: 10px; + font-weight: 500; +} + +.type-hot { + background: #ffe6e6; + color: #e74c3c; +} + +.type-new { + background: #e6f3ff; + color: #3498db; +} + +.type-default { + background: #f8f9fa; + color: #6c757d; +} + +/* 底部 */ +.footer { + text-align: center; + padding: 24px 0; + border-top: 1px solid #e8f5e8; + margin-top: 32px; +} + +.update-time { + font-size: 12px; + color: #95a5a6; +} + +/* 手机端优化 (默认) */ +@media (max-width: 768px) { + .container { + padding: 0 12px; + } + + .header { + padding: 20px 0; + } + + .title { + font-size: 24px; + } + + .subtitle { + font-size: 13px; + } + + .hot-item { + padding: 14px; + gap: 10px; + } + + .item-cover { + width: 60px; + height: 45px; + } + + .item-title { + font-size: 15px; + } + + .item-desc { + font-size: 12px; + } + + .rank { + width: 28px; + height: 28px; + font-size: 13px; + } +} + +/* 平板端适配 */ +@media (min-width: 769px) and (max-width: 1024px) { + .container { + padding: 0 24px; + } + + .hot-list { + grid-template-columns: repeat(1, 1fr); + gap: 18px; + } + + .title { + font-size: 32px; + } + + .hot-item { + padding: 18px; + } +} + +/* 电脑端适配 */ +@media (min-width: 1025px) { + .container { + padding: 0 32px; + } + + .hot-list { + grid-template-columns: repeat(1, 1fr); + gap: 20px; + } + + .title { + font-size: 36px; + } + + .hot-item { + padding: 20px; + gap: 16px; + } + + .item-cover { + width: 100px; + height: 75px; + } + + .item-title { + font-size: 17px; + } + + .item-desc { + font-size: 14px; + } +} + +/* 大屏幕优化 */ +@media (min-width: 1400px) { + .hot-list { + grid-template-columns: repeat(2, 1fr); + gap: 24px; + } +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/百度实时热搜/返回接口.json b/InfoGenie-frontend/public/60sapi/热搜榜单/百度实时热搜/返回接口.json new file mode 100644 index 00000000..0a68ca26 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/百度实时热搜/返回接口.json @@ -0,0 +1,606 @@ +{ + "code": 200, + "message": "获取成功。数据来自官方/权威源头,以确保稳定与实时。开源地址 https://github.com/vikiboss/60s,反馈群 595941841", + "data": [ + { + "rank": 1, + "title": "102岁老兵ICU看阅兵后安详离世", + "desc": "", + "score": "7807952", + "score_desc": "780.8w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/e190dea8327f8295c8a5883878fe6d14", + "type": "1", + "type_desc": "新", + "type_icon": "https://search-operate.cdn.bcebos.com/42e626c5469cc4cd3b91131bcfe53d44.png", + "url": "https://www.baidu.com/s?wd=102%E5%B2%81%E8%80%81%E5%85%B5ICU%E7%9C%8B%E9%98%85%E5%85%B5%E5%90%8E%E5%AE%89%E8%AF%A6%E7%A6%BB%E4%B8%96&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 2, + "title": "看阅兵明白了耿爽联合国发言含金量", + "desc": "", + "score": "7714187", + "score_desc": "771.42w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/83340b647c7a2f569c0a03482d5b40f1", + "type": "3", + "type_desc": "热", + "type_icon": "https://search-operate.cdn.bcebos.com/54a1ed72d00cd07334860b0509489d8b.png", + "url": "https://www.baidu.com/s?wd=%E7%9C%8B%E9%98%85%E5%85%B5%E6%98%8E%E7%99%BD%E4%BA%86%E8%80%BF%E7%88%BD%E8%81%94%E5%90%88%E5%9B%BD%E5%8F%91%E8%A8%80%E5%90%AB%E9%87%91%E9%87%8F&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 3, + "title": "80秒带你回顾阅兵“高燃瞬间”", + "desc": "", + "score": "7616477", + "score_desc": "761.65w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/a64eb808789c7bae99eb3e0f98a20621", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=80%E7%A7%92%E5%B8%A6%E4%BD%A0%E5%9B%9E%E9%A1%BE%E9%98%85%E5%85%B5%E2%80%9C%E9%AB%98%E7%87%83%E7%9E%AC%E9%97%B4%E2%80%9D&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 4, + "title": "新华社认证的帅兵哥已婚", + "desc": "", + "score": "7522472", + "score_desc": "752.25w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/493dd01d2abf915809eb1387e5b8a026", + "type": "1", + "type_desc": "新", + "type_icon": "https://search-operate.cdn.bcebos.com/42e626c5469cc4cd3b91131bcfe53d44.png", + "url": "https://www.baidu.com/s?wd=%E6%96%B0%E5%8D%8E%E7%A4%BE%E8%AE%A4%E8%AF%81%E7%9A%84%E5%B8%85%E5%85%B5%E5%93%A5%E5%B7%B2%E5%A9%9A&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 5, + "title": "普京记者会身后的大红灯笼亮了", + "desc": "", + "score": "7426902", + "score_desc": "742.69w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/1e895a56da47054e111ce225b1efd58f", + "type": "3", + "type_desc": "热", + "type_icon": "https://search-operate.cdn.bcebos.com/54a1ed72d00cd07334860b0509489d8b.png", + "url": "https://www.baidu.com/s?wd=%E6%99%AE%E4%BA%AC%E8%AE%B0%E8%80%85%E4%BC%9A%E8%BA%AB%E5%90%8E%E7%9A%84%E5%A4%A7%E7%BA%A2%E7%81%AF%E7%AC%BC%E4%BA%AE%E4%BA%86&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 6, + "title": "中国网警:烽火烬处 赓续前行", + "desc": "", + "score": "7332067", + "score_desc": "733.21w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/0d872743f2cfabc8fd9ee1da970a5fed", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD%E7%BD%91%E8%AD%A6%EF%BC%9A%E7%83%BD%E7%81%AB%E7%83%AC%E5%A4%84+%E8%B5%93%E7%BB%AD%E5%89%8D%E8%A1%8C&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 7, + "title": "“呼叫81192!” 这一刻含泪量太高", + "desc": "", + "score": "7237296", + "score_desc": "723.73w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/552c202f87db2219d6e150a39976bad7", + "type": "1", + "type_desc": "新", + "type_icon": "https://search-operate.cdn.bcebos.com/42e626c5469cc4cd3b91131bcfe53d44.png", + "url": "https://www.baidu.com/s?wd=%E2%80%9C%E5%91%BC%E5%8F%AB81192%EF%BC%81%E2%80%9D+%E8%BF%99%E4%B8%80%E5%88%BB%E5%90%AB%E6%B3%AA%E9%87%8F%E5%A4%AA%E9%AB%98&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 8, + "title": "天津和平鸽归巢主人激动吹哨迎接", + "desc": "", + "score": "7139286", + "score_desc": "713.93w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/1c5dfd83c55b6482d1307f310d5642a7", + "type": "3", + "type_desc": "热", + "type_icon": "https://search-operate.cdn.bcebos.com/54a1ed72d00cd07334860b0509489d8b.png", + "url": "https://www.baidu.com/s?wd=%E5%A4%A9%E6%B4%A5%E5%92%8C%E5%B9%B3%E9%B8%BD%E5%BD%92%E5%B7%A2%E4%B8%BB%E4%BA%BA%E6%BF%80%E5%8A%A8%E5%90%B9%E5%93%A8%E8%BF%8E%E6%8E%A5&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 9, + "title": "中国排面给全世界亿点点震撼", + "desc": "", + "score": "7042854", + "score_desc": "704.29w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/986b69bb82a32bbd72f4c90281ece503", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD%E6%8E%92%E9%9D%A2%E7%BB%99%E5%85%A8%E4%B8%96%E7%95%8C%E4%BA%BF%E7%82%B9%E7%82%B9%E9%9C%87%E6%92%BC&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 10, + "title": "8万只气球缘何直径都是26厘米左右", + "desc": "", + "score": "6943236", + "score_desc": "694.32w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/783293899ac972283b13501deb5772fa", + "type": "3", + "type_desc": "热", + "type_icon": "https://search-operate.cdn.bcebos.com/54a1ed72d00cd07334860b0509489d8b.png", + "url": "https://www.baidu.com/s?wd=8%E4%B8%87%E5%8F%AA%E6%B0%94%E7%90%83%E7%BC%98%E4%BD%95%E7%9B%B4%E5%BE%84%E9%83%BD%E6%98%AF26%E5%8E%98%E7%B1%B3%E5%B7%A6%E5%8F%B3&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 11, + "title": "江苏足协辟谣“苏超”要改名", + "desc": "近日,有部分自媒体称“苏超”已改名,对此,江苏省足协回应:“苏超”没有改名,也没有想过要改名。", + "score": "6853163", + "score_desc": "685.32w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/fe16124a5cd018feee2e941d05850e00", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E6%B1%9F%E8%8B%8F%E8%B6%B3%E5%8D%8F%E8%BE%9F%E8%B0%A3%E2%80%9C%E8%8B%8F%E8%B6%85%E2%80%9D%E8%A6%81%E6%94%B9%E5%90%8D&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 12, + "title": "金正恩只回了韩议长一个字", + "desc": "", + "score": "6760236", + "score_desc": "676.02w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/68824cd0db12d3d6b71f6d79dc9cd1e4", + "type": "3", + "type_desc": "热", + "type_icon": "https://search-operate.cdn.bcebos.com/54a1ed72d00cd07334860b0509489d8b.png", + "url": "https://www.baidu.com/s?wd=%E9%87%91%E6%AD%A3%E6%81%A9%E5%8F%AA%E5%9B%9E%E4%BA%86%E9%9F%A9%E8%AE%AE%E9%95%BF%E4%B8%80%E4%B8%AA%E5%AD%97&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 13, + "title": "特朗普称看了九三阅兵:很精彩很震撼", + "desc": "", + "score": "6656922", + "score_desc": "665.69w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/bb902e423148eb1e83e78955f2eb9adb", + "type": "3", + "type_desc": "热", + "type_icon": "https://search-operate.cdn.bcebos.com/54a1ed72d00cd07334860b0509489d8b.png", + "url": "https://www.baidu.com/s?wd=%E7%89%B9%E6%9C%97%E6%99%AE%E7%A7%B0%E7%9C%8B%E4%BA%86%E4%B9%9D%E4%B8%89%E9%98%85%E5%85%B5%EF%BC%9A%E5%BE%88%E7%B2%BE%E5%BD%A9%E5%BE%88%E9%9C%87%E6%92%BC&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 14, + "title": "韩国高铁站直播九三阅兵", + "desc": "", + "score": "6566970", + "score_desc": "656.7w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/b68cb01b4b20989cea82c78c9fe39c3b", + "type": "3", + "type_desc": "热", + "type_icon": "https://search-operate.cdn.bcebos.com/54a1ed72d00cd07334860b0509489d8b.png", + "url": "https://www.baidu.com/s?wd=%E9%9F%A9%E5%9B%BD%E9%AB%98%E9%93%81%E7%AB%99%E7%9B%B4%E6%92%AD%E4%B9%9D%E4%B8%89%E9%98%85%E5%85%B5&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 15, + "title": "在中国的加沙人看阅兵时落泪", + "desc": "", + "score": "6476621", + "score_desc": "647.66w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/f16f082786ac14ea20dc709c527dec4b", + "type": "3", + "type_desc": "热", + "type_icon": "https://search-operate.cdn.bcebos.com/54a1ed72d00cd07334860b0509489d8b.png", + "url": "https://www.baidu.com/s?wd=%E5%9C%A8%E4%B8%AD%E5%9B%BD%E7%9A%84%E5%8A%A0%E6%B2%99%E4%BA%BA%E7%9C%8B%E9%98%85%E5%85%B5%E6%97%B6%E8%90%BD%E6%B3%AA&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 16, + "title": "专家:东风-61出现改变命名规则", + "desc": "", + "score": "6376137", + "score_desc": "637.61w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/66c1c659e7b1a37732b2735253716d60", + "type": "3", + "type_desc": "热", + "type_icon": "https://search-operate.cdn.bcebos.com/54a1ed72d00cd07334860b0509489d8b.png", + "url": "https://www.baidu.com/s?wd=%E4%B8%93%E5%AE%B6%EF%BC%9A%E4%B8%9C%E9%A3%8E-61%E5%87%BA%E7%8E%B0%E6%94%B9%E5%8F%98%E5%91%BD%E5%90%8D%E8%A7%84%E5%88%99&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 17, + "title": "军嫂盯着徒步方队找丈夫迷糊了", + "desc": "", + "score": "6274961", + "score_desc": "627.5w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/90ac62b9f3b3365dc7fed40c62259a9f", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E5%86%9B%E5%AB%82%E7%9B%AF%E7%9D%80%E5%BE%92%E6%AD%A5%E6%96%B9%E9%98%9F%E6%89%BE%E4%B8%88%E5%A4%AB%E8%BF%B7%E7%B3%8A%E4%BA%86&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 18, + "title": "普京调侃佩斯科夫:懒虫 不想工作", + "desc": "", + "score": "6180590", + "score_desc": "618.06w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/8e9fae0b3a1b23049cfdb9323d6a1efe", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E6%99%AE%E4%BA%AC%E8%B0%83%E4%BE%83%E4%BD%A9%E6%96%AF%E7%A7%91%E5%A4%AB%EF%BC%9A%E6%87%92%E8%99%AB+%E4%B8%8D%E6%83%B3%E5%B7%A5%E4%BD%9C&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 19, + "title": "原陆军第31集团军军长王昭堃逝世", + "desc": "", + "score": "6089180", + "score_desc": "608.92w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/778f1aa16cdfc4db09926956ae5b5741", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E5%8E%9F%E9%99%86%E5%86%9B%E7%AC%AC31%E9%9B%86%E5%9B%A2%E5%86%9B%E5%86%9B%E9%95%BF%E7%8E%8B%E6%98%AD%E5%A0%83%E9%80%9D%E4%B8%96&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 20, + "title": "“防霸凌”儿童指纹水杯被吐槽费妈", + "desc": "", + "score": "5986581", + "score_desc": "598.66w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/c590f4412c1aa6904b65a94cba7de275", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E2%80%9C%E9%98%B2%E9%9C%B8%E5%87%8C%E2%80%9D%E5%84%BF%E7%AB%A5%E6%8C%87%E7%BA%B9%E6%B0%B4%E6%9D%AF%E8%A2%AB%E5%90%90%E6%A7%BD%E8%B4%B9%E5%A6%88&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 21, + "title": "特朗普下令重振美国军队", + "desc": "", + "score": "5902417", + "score_desc": "590.24w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/de99b4697f6d926890dc31d686c1222c", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E7%89%B9%E6%9C%97%E6%99%AE%E4%B8%8B%E4%BB%A4%E9%87%8D%E6%8C%AF%E7%BE%8E%E5%9B%BD%E5%86%9B%E9%98%9F&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 22, + "title": "间谍张某某死缓:出轨外国女官员生子", + "desc": "", + "score": "5790606", + "score_desc": "579.06w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/f93c1366d41c7cfbb2383dcb17449c28", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E9%97%B4%E8%B0%8D%E5%BC%A0%E6%9F%90%E6%9F%90%E6%AD%BB%E7%BC%93%EF%BC%9A%E5%87%BA%E8%BD%A8%E5%A4%96%E5%9B%BD%E5%A5%B3%E5%AE%98%E5%91%98%E7%94%9F%E5%AD%90&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 23, + "title": "5万余人观礼离场后干干净净", + "desc": "", + "score": "5717616", + "score_desc": "571.76w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/53c6b971cef08daf3104bb5133b4b6ed", + "type": "3", + "type_desc": "热", + "type_icon": "https://search-operate.cdn.bcebos.com/54a1ed72d00cd07334860b0509489d8b.png", + "url": "https://www.baidu.com/s?wd=5%E4%B8%87%E4%BD%99%E4%BA%BA%E8%A7%82%E7%A4%BC%E7%A6%BB%E5%9C%BA%E5%90%8E%E5%B9%B2%E5%B9%B2%E5%87%80%E5%87%80&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 24, + "title": "普京乘机回国 王毅送行", + "desc": "", + "score": "5607811", + "score_desc": "560.78w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/5f7afddd2e0a570573b245b6f31a1338", + "type": "1", + "type_desc": "新", + "type_icon": "https://search-operate.cdn.bcebos.com/42e626c5469cc4cd3b91131bcfe53d44.png", + "url": "https://www.baidu.com/s?wd=%E6%99%AE%E4%BA%AC%E4%B9%98%E6%9C%BA%E5%9B%9E%E5%9B%BD+%E7%8E%8B%E6%AF%85%E9%80%81%E8%A1%8C&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 25, + "title": "刘老庄连战旗为何多了一个点", + "desc": "", + "score": "5513446", + "score_desc": "551.34w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/7084449234aed77c74438ca263fdcd58", + "type": "1", + "type_desc": "新", + "type_icon": "https://search-operate.cdn.bcebos.com/42e626c5469cc4cd3b91131bcfe53d44.png", + "url": "https://www.baidu.com/s?wd=%E5%88%98%E8%80%81%E5%BA%84%E8%BF%9E%E6%88%98%E6%97%97%E4%B8%BA%E4%BD%95%E5%A4%9A%E4%BA%86%E4%B8%80%E4%B8%AA%E7%82%B9&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 26, + "title": "迎面感受东风-61东风-5C的视觉冲击", + "desc": "", + "score": "5426660", + "score_desc": "542.67w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/40210a63cf69ddbbedbe59a19730e374", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E8%BF%8E%E9%9D%A2%E6%84%9F%E5%8F%97%E4%B8%9C%E9%A3%8E-61%E4%B8%9C%E9%A3%8E-5C%E7%9A%84%E8%A7%86%E8%A7%89%E5%86%B2%E5%87%BB&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 27, + "title": "阅兵当天的北京处处都有追飞机的人", + "desc": "", + "score": "5336487", + "score_desc": "533.65w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/1513230ae41ba37f680dccbc526b7145", + "type": "3", + "type_desc": "热", + "type_icon": "https://search-operate.cdn.bcebos.com/54a1ed72d00cd07334860b0509489d8b.png", + "url": "https://www.baidu.com/s?wd=%E9%98%85%E5%85%B5%E5%BD%93%E5%A4%A9%E7%9A%84%E5%8C%97%E4%BA%AC%E5%A4%84%E5%A4%84%E9%83%BD%E6%9C%89%E8%BF%BD%E9%A3%9E%E6%9C%BA%E7%9A%84%E4%BA%BA&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 28, + "title": "歼-35大片来了", + "desc": "", + "score": "5240364", + "score_desc": "524.04w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/017c3b52514fb3ae83405da1da5fc350", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E6%AD%BC-35%E5%A4%A7%E7%89%87%E6%9D%A5%E4%BA%86&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 29, + "title": "普京透露与特朗普“车内密谈”细节", + "desc": "", + "score": "5123571", + "score_desc": "512.36w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/5548e90353e4696a1116ffc0e65e086d", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E6%99%AE%E4%BA%AC%E9%80%8F%E9%9C%B2%E4%B8%8E%E7%89%B9%E6%9C%97%E6%99%AE%E2%80%9C%E8%BD%A6%E5%86%85%E5%AF%86%E8%B0%88%E2%80%9D%E7%BB%86%E8%8A%82&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 30, + "title": "和平鸽从天津到北京出差参加阅兵", + "desc": "", + "score": "5037077", + "score_desc": "503.71w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/f4558c31275119cfab564cadeddf6f50", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E5%92%8C%E5%B9%B3%E9%B8%BD%E4%BB%8E%E5%A4%A9%E6%B4%A5%E5%88%B0%E5%8C%97%E4%BA%AC%E5%87%BA%E5%B7%AE%E5%8F%82%E5%8A%A0%E9%98%85%E5%85%B5&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 31, + "title": "王毅送中国跑鞋 匈牙利外长爱不释手", + "desc": "", + "score": "4950481", + "score_desc": "495.05w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/95df9511f4c0951f823f387f3286c029", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E7%8E%8B%E6%AF%85%E9%80%81%E4%B8%AD%E5%9B%BD%E8%B7%91%E9%9E%8B+%E5%8C%88%E7%89%99%E5%88%A9%E5%A4%96%E9%95%BF%E7%88%B1%E4%B8%8D%E9%87%8A%E6%89%8B&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 32, + "title": "郑钦文晒东风5C帅照", + "desc": "", + "score": "4841678", + "score_desc": "484.17w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/5e2fec1c090ce966a2dd89071342d3e9", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E9%83%91%E9%92%A6%E6%96%87%E6%99%92%E4%B8%9C%E9%A3%8E5C%E5%B8%85%E7%85%A7&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 33, + "title": "阅兵当天 北京街头成为别样观礼台", + "desc": "", + "score": "4760831", + "score_desc": "476.08w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/a6495a07da318dc9644f77de370b8035", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E9%98%85%E5%85%B5%E5%BD%93%E5%A4%A9+%E5%8C%97%E4%BA%AC%E8%A1%97%E5%A4%B4%E6%88%90%E4%B8%BA%E5%88%AB%E6%A0%B7%E8%A7%82%E7%A4%BC%E5%8F%B0&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 34, + "title": "华春莹与记者互动:我的心情和你一样", + "desc": "", + "score": "4651512", + "score_desc": "465.15w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/4377037f24b931479efc20e2a7b87776", + "type": "3", + "type_desc": "热", + "type_icon": "https://search-operate.cdn.bcebos.com/54a1ed72d00cd07334860b0509489d8b.png", + "url": "https://www.baidu.com/s?wd=%E5%8D%8E%E6%98%A5%E8%8E%B9%E4%B8%8E%E8%AE%B0%E8%80%85%E4%BA%92%E5%8A%A8%EF%BC%9A%E6%88%91%E7%9A%84%E5%BF%83%E6%83%85%E5%92%8C%E4%BD%A0%E4%B8%80%E6%A0%B7&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 35, + "title": "父亲称女民兵方队领队是全家的骄傲", + "desc": "", + "score": "4566469", + "score_desc": "456.65w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/79b1620e703b1e73fd5db686d6314ea0", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E7%88%B6%E4%BA%B2%E7%A7%B0%E5%A5%B3%E6%B0%91%E5%85%B5%E6%96%B9%E9%98%9F%E9%A2%86%E9%98%9F%E6%98%AF%E5%85%A8%E5%AE%B6%E7%9A%84%E9%AA%84%E5%82%B2&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 36, + "title": "宝宝出生恰逢阅兵 家人取名袁安阅", + "desc": "", + "score": "4470561", + "score_desc": "447.06w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/a5063fd737daf1da7a969e36ab672ed8", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E5%AE%9D%E5%AE%9D%E5%87%BA%E7%94%9F%E6%81%B0%E9%80%A2%E9%98%85%E5%85%B5+%E5%AE%B6%E4%BA%BA%E5%8F%96%E5%90%8D%E8%A2%81%E5%AE%89%E9%98%85&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 37, + "title": "特朗普承认观看中国阅兵", + "desc": "", + "score": "4353451", + "score_desc": "435.35w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/e7c27a7640bc0f9d25dcd7ad79026ce7", + "type": "3", + "type_desc": "热", + "type_icon": "https://search-operate.cdn.bcebos.com/54a1ed72d00cd07334860b0509489d8b.png", + "url": "https://www.baidu.com/s?wd=%E7%89%B9%E6%9C%97%E6%99%AE%E6%89%BF%E8%AE%A4%E8%A7%82%E7%9C%8B%E4%B8%AD%E5%9B%BD%E9%98%85%E5%85%B5&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 38, + "title": "一地官宣:3孩家庭购房补贴20万元", + "desc": "", + "score": "4290101", + "score_desc": "429.01w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/507444a742944d2ed619b480fdab147e", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E4%B8%80%E5%9C%B0%E5%AE%98%E5%AE%A3%EF%BC%9A3%E5%AD%A9%E5%AE%B6%E5%BA%AD%E8%B4%AD%E6%88%BF%E8%A1%A5%E8%B4%B420%E4%B8%87%E5%85%83&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 39, + "title": "OpenAI启动员工百亿美元售股", + "desc": "", + "score": "4172580", + "score_desc": "417.26w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/fc06e36007c4b957bee693b9abe64693", + "type": "1", + "type_desc": "新", + "type_icon": "https://search-operate.cdn.bcebos.com/42e626c5469cc4cd3b91131bcfe53d44.png", + "url": "https://www.baidu.com/s?wd=OpenAI%E5%90%AF%E5%8A%A8%E5%91%98%E5%B7%A5%E7%99%BE%E4%BA%BF%E7%BE%8E%E5%85%83%E5%94%AE%E8%82%A1&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 40, + "title": "想入军迷圈的 现在正是好时候", + "desc": "", + "score": "4098627", + "score_desc": "409.86w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/d5bde24cc4eed187d500f3e7a9d73f2d", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E6%83%B3%E5%85%A5%E5%86%9B%E8%BF%B7%E5%9C%88%E7%9A%84+%E7%8E%B0%E5%9C%A8%E6%AD%A3%E6%98%AF%E5%A5%BD%E6%97%B6%E5%80%99&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 41, + "title": "九三阅兵台湾线上播放超500万", + "desc": "", + "score": "3999782", + "score_desc": "399.98w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/ebfee25839294c24ca24af788fbd92bd", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E4%B9%9D%E4%B8%89%E9%98%85%E5%85%B5%E5%8F%B0%E6%B9%BE%E7%BA%BF%E4%B8%8A%E6%92%AD%E6%94%BE%E8%B6%85500%E4%B8%87&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 42, + "title": "信鸽协会回应市民救助落水和平鸽", + "desc": "", + "score": "3886482", + "score_desc": "388.65w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/dc5ce78481f36774922add0eb7076ec7", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E4%BF%A1%E9%B8%BD%E5%8D%8F%E4%BC%9A%E5%9B%9E%E5%BA%94%E5%B8%82%E6%B0%91%E6%95%91%E5%8A%A9%E8%90%BD%E6%B0%B4%E5%92%8C%E5%B9%B3%E9%B8%BD&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 43, + "title": "台退将看阅兵新装备直呼自己是军盲", + "desc": "", + "score": "3794294", + "score_desc": "379.43w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/686bb8c544ec3d0bc9f01f7ccd31195c", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E5%8F%B0%E9%80%80%E5%B0%86%E7%9C%8B%E9%98%85%E5%85%B5%E6%96%B0%E8%A3%85%E5%A4%87%E7%9B%B4%E5%91%BC%E8%87%AA%E5%B7%B1%E6%98%AF%E5%86%9B%E7%9B%B2&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 44, + "title": "多国来华领导人接连发声", + "desc": "", + "score": "3679787", + "score_desc": "367.98w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/a7f9ac9aaeb54422c70870ac9ab36d09", + "type": "3", + "type_desc": "热", + "type_icon": "https://search-operate.cdn.bcebos.com/54a1ed72d00cd07334860b0509489d8b.png", + "url": "https://www.baidu.com/s?wd=%E5%A4%9A%E5%9B%BD%E6%9D%A5%E5%8D%8E%E9%A2%86%E5%AF%BC%E4%BA%BA%E6%8E%A5%E8%BF%9E%E5%8F%91%E5%A3%B0&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 45, + "title": "河南佛教协会:释永信枉费僧众信任", + "desc": "", + "score": "3589427", + "score_desc": "358.94w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/279b2b9632b9d7776a62fccefbc058db", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E6%B2%B3%E5%8D%97%E4%BD%9B%E6%95%99%E5%8D%8F%E4%BC%9A%EF%BC%9A%E9%87%8A%E6%B0%B8%E4%BF%A1%E6%9E%89%E8%B4%B9%E5%83%A7%E4%BC%97%E4%BF%A1%E4%BB%BB&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 46, + "title": "揭秘阅兵地铁专列:143趟车接送2万人", + "desc": "", + "score": "3501916", + "score_desc": "350.19w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/711c2769ad7f6071171e7c11908c9f7a", + "type": "1", + "type_desc": "新", + "type_icon": "https://search-operate.cdn.bcebos.com/42e626c5469cc4cd3b91131bcfe53d44.png", + "url": "https://www.baidu.com/s?wd=%E6%8F%AD%E7%A7%98%E9%98%85%E5%85%B5%E5%9C%B0%E9%93%81%E4%B8%93%E5%88%97%EF%BC%9A143%E8%B6%9F%E8%BD%A6%E6%8E%A5%E9%80%812%E4%B8%87%E4%BA%BA&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 47, + "title": "苑举正观礼听到《黄河大合唱》落泪", + "desc": "", + "score": "3431345", + "score_desc": "343.13w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/ea02d87734137d71f4a1529a5cb864c7", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E8%8B%91%E4%B8%BE%E6%AD%A3%E8%A7%82%E7%A4%BC%E5%90%AC%E5%88%B0%E3%80%8A%E9%BB%84%E6%B2%B3%E5%A4%A7%E5%90%88%E5%94%B1%E3%80%8B%E8%90%BD%E6%B3%AA&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 48, + "title": "九三阅兵解锁了这些“首次”", + "desc": "", + "score": "3339123", + "score_desc": "333.91w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/35812fb7bcf6ff0d71f52f60fb9055fa", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E4%B9%9D%E4%B8%89%E9%98%85%E5%85%B5%E8%A7%A3%E9%94%81%E4%BA%86%E8%BF%99%E4%BA%9B%E2%80%9C%E9%A6%96%E6%AC%A1%E2%80%9D&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 49, + "title": "中国首起反规避调查", + "desc": "", + "score": "3210675", + "score_desc": "321.07w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/fa9ce1dd50ddb58eab40b7de920a0d79", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD%E9%A6%96%E8%B5%B7%E5%8F%8D%E8%A7%84%E9%81%BF%E8%B0%83%E6%9F%A5&sa=fyb_news&rsv_dl=fyb_news" + }, + { + "rank": 50, + "title": "王楚钦:被祖国的强大深深触动", + "desc": "", + "score": "3147784", + "score_desc": "314.78w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/d8ae151e1eefdec0449a52574f58ee51", + "type": "0", + "type_desc": null, + "type_icon": null, + "url": "https://www.baidu.com/s?wd=%E7%8E%8B%E6%A5%9A%E9%92%A6%EF%BC%9A%E8%A2%AB%E7%A5%96%E5%9B%BD%E7%9A%84%E5%BC%BA%E5%A4%A7%E6%B7%B1%E6%B7%B1%E8%A7%A6%E5%8A%A8&sa=fyb_news&rsv_dl=fyb_news" + } + ] +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/百度电视剧榜/background.css b/InfoGenie-frontend/public/60sapi/热搜榜单/百度电视剧榜/background.css new file mode 100644 index 00000000..06eae404 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/百度电视剧榜/background.css @@ -0,0 +1,242 @@ +/* 页面主背景 */ +body { + background: linear-gradient(135deg, #f9fbe7 0%, #f1f8e9 25%, #e8f5e8 50%, #dcedc8 75%, #c5e1a5 100%); + background-attachment: fixed; + position: relative; +} + +/* 背景装饰元素 */ +body::before { + content: ''; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-image: + radial-gradient(circle at 20% 80%, rgba(139, 195, 74, 0.06) 0%, transparent 50%), + radial-gradient(circle at 80% 20%, rgba(205, 220, 57, 0.06) 0%, transparent 50%), + radial-gradient(circle at 40% 40%, rgba(212, 225, 87, 0.08) 0%, transparent 50%); + pointer-events: none; + z-index: -1; +} + +/* 容器背景 */ +.container { + background: rgba(255, 255, 255, 0.75); + backdrop-filter: blur(10px); + border-radius: 16px; + box-shadow: 0 8px 32px rgba(139, 195, 74, 0.12); + margin-top: 20px; + margin-bottom: 20px; + border: 1px solid rgba(241, 248, 233, 0.5); +} + +/* 头部背景 */ +.header { + background: linear-gradient(135deg, rgba(139, 195, 74, 0.08) 0%, rgba(205, 220, 57, 0.08) 100%); + border-radius: 16px 16px 0 0; + position: relative; + overflow: hidden; +} + +.header::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: + radial-gradient(circle at 30% 20%, rgba(139, 195, 74, 0.12) 0%, transparent 40%), + radial-gradient(circle at 70% 80%, rgba(205, 220, 57, 0.1) 0%, transparent 40%); + pointer-events: none; +} + +/* 电视剧项目背景 */ +.tv-item { + background: rgba(255, 255, 255, 0.92); + backdrop-filter: blur(8px); + position: relative; + overflow: hidden; +} + +.tv-item::after { + content: ''; + position: absolute; + top: 0; + right: 0; + width: 60px; + height: 100%; + background: linear-gradient(90deg, transparent 0%, rgba(139, 195, 74, 0.03) 100%); + pointer-events: none; +} + +/* 前三名特殊背景效果 */ +.tv-item:nth-child(1) { + background: linear-gradient(135deg, rgba(244, 67, 54, 0.06) 0%, rgba(255, 255, 255, 0.96) 100%); +} + +.tv-item:nth-child(2) { + background: linear-gradient(135deg, rgba(255, 152, 0, 0.06) 0%, rgba(255, 255, 255, 0.96) 100%); +} + +.tv-item:nth-child(3) { + background: linear-gradient(135deg, rgba(255, 193, 7, 0.06) 0%, rgba(255, 255, 255, 0.96) 100%); +} + +/* 加载状态背景 */ +.loading { + background: rgba(255, 255, 255, 0.85); + backdrop-filter: blur(8px); + border-radius: 12px; + margin: 20px; + border: 1px solid rgba(241, 248, 233, 0.3); +} + +/* 错误信息背景 */ +.error-message { + background: linear-gradient(135deg, rgba(231, 76, 60, 0.06) 0%, rgba(255, 255, 255, 0.92) 100%); + backdrop-filter: blur(8px); + border-radius: 12px; + border: 1px solid rgba(231, 76, 60, 0.1); + margin: 20px; +} + +/* 底部背景 */ +.footer { + background: linear-gradient(135deg, rgba(139, 195, 74, 0.04) 0%, rgba(205, 220, 57, 0.04) 100%); + border-radius: 0 0 16px 16px; + position: relative; +} + +.footer::before { + content: ''; + position: absolute; + top: 0; + left: 50%; + transform: translateX(-50%); + width: 60px; + height: 1px; + background: linear-gradient(90deg, transparent 0%, rgba(139, 195, 74, 0.4) 50%, transparent 100%); +} + +/* 封面图片背景效果 */ +.item-cover { + position: relative; + overflow: hidden; +} + +.item-cover::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: linear-gradient(45deg, rgba(139, 195, 74, 0.05) 0%, transparent 50%); + pointer-events: none; + opacity: 0; + transition: opacity 0.3s ease; +} + +.tv-item:hover .item-cover::before { + opacity: 1; +} + +/* 响应式背景调整 */ +@media (max-width: 768px) { + .container { + margin-top: 10px; + margin-bottom: 10px; + border-radius: 12px; + } + + .header { + border-radius: 12px 12px 0 0; + } + + .footer { + border-radius: 0 0 12px 12px; + } + + body::before { + background-image: + radial-gradient(circle at 20% 80%, rgba(139, 195, 74, 0.04) 0%, transparent 40%), + radial-gradient(circle at 80% 20%, rgba(205, 220, 57, 0.04) 0%, transparent 40%); + } +} + +@media (min-width: 1025px) { + .container { + margin-top: 40px; + margin-bottom: 40px; + } + + body::before { + background-image: + radial-gradient(circle at 15% 85%, rgba(139, 195, 74, 0.08) 0%, transparent 60%), + radial-gradient(circle at 85% 15%, rgba(205, 220, 57, 0.08) 0%, transparent 60%), + radial-gradient(circle at 50% 50%, rgba(212, 225, 87, 0.06) 0%, transparent 70%); + } +} + +/* 动画效果 */ +@keyframes backgroundShift { + 0% { + background-position: 0% 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0% 50%; + } +} + +/* 悬浮时的背景变化 */ +.tv-item:hover { + background: rgba(255, 255, 255, 0.98); +} + +.tv-item:hover::after { + background: linear-gradient(90deg, transparent 0%, rgba(139, 195, 74, 0.06) 100%); +} + +/* 排名背景渐变 */ +.rank { + position: relative; + overflow: hidden; +} + +.rank::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: linear-gradient(45deg, rgba(255, 255, 255, 0.25) 0%, transparent 100%); + pointer-events: none; +} + +/* 按钮背景效果 */ +.retry-btn { + position: relative; + overflow: hidden; +} + +.retry-btn::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.3) 50%, transparent 100%); + transition: left 0.5s ease; +} + +.retry-btn:hover::before { + left: 100%; +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/百度电视剧榜/index.html b/InfoGenie-frontend/public/60sapi/热搜榜单/百度电视剧榜/index.html new file mode 100644 index 00000000..7c40d9f2 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/百度电视剧榜/index.html @@ -0,0 +1,40 @@ + + + + + + 百度电视剧榜单 + + + + +
+
+

百度电视剧榜单

+

实时热门电视剧,追剧必看榜单

+
+ +
+
+
+

正在加载电视剧榜单...

+
+ + + + +
+ +
+

+
+
+ + + + \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/百度电视剧榜/script.js b/InfoGenie-frontend/public/60sapi/热搜榜单/百度电视剧榜/script.js new file mode 100644 index 00000000..b1174db4 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/百度电视剧榜/script.js @@ -0,0 +1,267 @@ +// DOM元素获取 +const loadingElement = document.getElementById('loading'); +const errorElement = document.getElementById('error'); +const tvListElement = document.getElementById('tvList'); +const updateTimeElement = document.getElementById('updateTime'); + +// 页面加载完成后初始化 +document.addEventListener('DOMContentLoaded', function() { + loadData(); + + // 每5分钟自动刷新数据 + setInterval(loadData, 5 * 60 * 1000); + + // 监听页面可见性变化,页面重新可见时刷新数据 + document.addEventListener('visibilitychange', function() { + if (!document.hidden) { + loadData(); + } + }); + + // 监听网络状态变化 + window.addEventListener('online', loadData); +}); + +// 加载数据函数 +async function loadData() { + try { + showLoading(); + + // 调用百度电视剧榜API + const response = await fetch('https://60s.api.shumengya.top/v2/baidu/teleplay'); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + + if (data.code === 200 && data.data) { + renderTvList(data.data); + updateTime(); + hideLoading(); + } else { + throw new Error(data.message || '数据格式错误'); + } + + } catch (error) { + console.error('加载数据失败:', error); + showError(); + } +} + +// 渲染电视剧列表 +function renderTvList(tvData) { + if (!tvData || !Array.isArray(tvData)) { + showError(); + return; + } + + const listHTML = tvData.map((item, index) => { + const rank = item.rank || (index + 1); + const rankClass = rank <= 3 ? (rank === 1 ? 'top1' : 'top3') : ''; + + // 处理封面图片 + const coverImg = item.cover ? + `${item.title}` : + ''; + + // 处理描述信息 + const description = item.desc || ''; + + // 处理评分信息 + const score = item.score || ''; + const scoreDesc = item.score_desc || ''; + + // 处理链接 + const linkUrl = item.url || '#'; + + return ` +
+
${rank}
+ ${coverImg} +
+
+

${item.title || '无标题'}

+
+ ${description ? `

${description}

` : ''} + +
+
+ `; + }).join(''); + + tvListElement.innerHTML = listHTML; + tvListElement.style.display = 'block'; +} + +// 格式化评分 +function formatScore(score) { + if (!score) return ''; + + // 如果是数字,进行格式化 + if (typeof score === 'number') { + if (score >= 10000) { + return (score / 10000).toFixed(1) + '万'; + } + return score.toString(); + } + + // 如果是字符串,直接返回 + return score.toString(); +} + +// 打开链接 +function openLink(url) { + if (url && url !== '#') { + window.open(url, '_blank'); + } +} + +// 显示加载状态 +function showLoading() { + loadingElement.style.display = 'block'; + errorElement.style.display = 'none'; + tvListElement.style.display = 'none'; +} + +// 隐藏加载状态 +function hideLoading() { + loadingElement.style.display = 'none'; +} + +// 显示错误信息 +function showError() { + loadingElement.style.display = 'none'; + errorElement.style.display = 'block'; + tvListElement.style.display = 'none'; +} + +// 更新时间显示 +function updateTime() { + const now = new Date(); + const timeString = now.toLocaleString('zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + }); + updateTimeElement.textContent = `最后更新时间: ${timeString}`; +} + +// 重试加载数据 +function retryLoad() { + loadData(); +} + +// 页面滚动优化 +let ticking = false; + +function updateScrollPosition() { + // 可以在这里添加滚动相关的优化逻辑 + ticking = false; +} + +window.addEventListener('scroll', function() { + if (!ticking) { + requestAnimationFrame(updateScrollPosition); + ticking = true; + } +}); + +// 错误处理和日志记录 +window.addEventListener('error', function(e) { + console.error('页面错误:', e.error); +}); + +window.addEventListener('unhandledrejection', function(e) { + console.error('未处理的Promise拒绝:', e.reason); +}); + +// 性能监控 +if ('performance' in window) { + window.addEventListener('load', function() { + setTimeout(function() { + const perfData = performance.timing; + const loadTime = perfData.loadEventEnd - perfData.navigationStart; + console.log('页面加载时间:', loadTime + 'ms'); + }, 0); + }); +} + +// 图片懒加载优化 +function lazyLoadImages() { + const images = document.querySelectorAll('.item-cover'); + const imageObserver = new IntersectionObserver((entries, observer) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + const img = entry.target; + img.src = img.dataset.src; + img.classList.remove('lazy'); + imageObserver.unobserve(img); + } + }); + }); + + images.forEach(img => imageObserver.observe(img)); +} + +// 添加键盘导航支持 +document.addEventListener('keydown', function(e) { + const items = document.querySelectorAll('.tv-item'); + const currentFocus = document.activeElement; + let currentIndex = Array.from(items).indexOf(currentFocus); + + switch(e.key) { + case 'ArrowDown': + e.preventDefault(); + currentIndex = Math.min(currentIndex + 1, items.length - 1); + items[currentIndex]?.focus(); + break; + case 'ArrowUp': + e.preventDefault(); + currentIndex = Math.max(currentIndex - 1, 0); + items[currentIndex]?.focus(); + break; + case 'Enter': + if (currentFocus && currentFocus.classList.contains('tv-item')) { + currentFocus.click(); + } + break; + } +}); + +// 使电视剧项目可聚焦 +document.addEventListener('DOMContentLoaded', function() { + const style = document.createElement('style'); + style.textContent = ` + .tv-item { + outline: none; + transition: all 0.3s ease; + } + .tv-item:focus { + transform: translateY(-2px); + box-shadow: 0 4px 16px rgba(139, 195, 74, 0.25); + border-color: #8bc34a; + } + `; + document.head.appendChild(style); + + // 为所有电视剧项目添加tabindex + setTimeout(() => { + const items = document.querySelectorAll('.tv-item'); + items.forEach((item, index) => { + item.setAttribute('tabindex', '0'); + }); + }, 100); +}); \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/百度电视剧榜/styles.css b/InfoGenie-frontend/public/60sapi/热搜榜单/百度电视剧榜/styles.css new file mode 100644 index 00000000..7953479d --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/百度电视剧榜/styles.css @@ -0,0 +1,378 @@ +/* 基础样式重置 */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; + line-height: 1.6; + color: #2c3e50; + overflow-x: hidden; +} + +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 16px; + min-height: 100vh; + display: flex; + flex-direction: column; +} + +/* 头部样式 */ +.header { + text-align: center; + padding: 24px 0; + border-bottom: 2px solid #d4e157; + margin-bottom: 24px; +} + +.title { + font-size: 28px; + font-weight: 700; + background: linear-gradient(135deg, #8bc34a, #cddc39); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + margin-bottom: 8px; + text-shadow: 0 2px 4px rgba(139, 195, 74, 0.1); +} + +.subtitle { + font-size: 14px; + color: #7f8c8d; + font-weight: 400; +} + +/* 主内容区域 */ +.main-content { + flex: 1; + position: relative; +} + +/* 加载状态 */ +.loading { + text-align: center; + padding: 60px 20px; + color: #8bc34a; +} + +.loading-spinner { + width: 40px; + height: 40px; + border: 3px solid #d4e157; + border-top: 3px solid #8bc34a; + border-radius: 50%; + animation: spin 1s linear infinite; + margin: 0 auto 16px; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* 错误信息 */ +.error-message { + text-align: center; + padding: 40px 20px; + color: #e74c3c; +} + +.retry-btn { + background: linear-gradient(135deg, #8bc34a, #cddc39); + color: white; + border: none; + padding: 10px 20px; + border-radius: 20px; + cursor: pointer; + font-size: 14px; + margin-top: 16px; + transition: all 0.3s ease; + box-shadow: 0 2px 8px rgba(139, 195, 74, 0.3); +} + +.retry-btn:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(139, 195, 74, 0.4); +} + +/* 电视剧列表 */ +.tv-list { + display: grid; + gap: 16px; +} + +.tv-item { + background: #ffffff; + border: 1px solid #f1f8e9; + border-radius: 12px; + padding: 16px; + transition: all 0.3s ease; + box-shadow: 0 2px 8px rgba(139, 195, 74, 0.08); + position: relative; + overflow: hidden; + display: flex; + gap: 12px; + cursor: pointer; +} + +.tv-item:hover { + transform: translateY(-2px); + box-shadow: 0 4px 16px rgba(139, 195, 74, 0.15); + border-color: #d4e157; +} + +.tv-item::before { + content: ''; + position: absolute; + left: 0; + top: 0; + width: 4px; + height: 100%; + background: linear-gradient(to bottom, #8bc34a, #cddc39); +} + +/* 排名样式 */ +.rank { + background: linear-gradient(135deg, #8bc34a, #cddc39); + color: white; + width: 32px; + height: 32px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + font-size: 14px; + flex-shrink: 0; + margin-top: 4px; + box-shadow: 0 2px 6px rgba(139, 195, 74, 0.3); +} + +.rank.top3 { + background: linear-gradient(135deg, #ff9800, #ffc107); +} + +.rank.top1 { + background: linear-gradient(135deg, #f44336, #e91e63); +} + +/* 封面图片 */ +.item-cover { + width: 80px; + height: 100px; + border-radius: 8px; + object-fit: cover; + flex-shrink: 0; + border: 1px solid #f1f8e9; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +/* 内容区域 */ +.item-content { + flex: 1; + display: flex; + flex-direction: column; + justify-content: space-between; + min-height: 100px; +} + +.item-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + margin-bottom: 8px; +} + +.item-title { + font-size: 16px; + font-weight: 600; + color: #2c3e50; + line-height: 1.4; + margin-bottom: 4px; + transition: color 0.3s ease; + flex: 1; +} + +.item-title:hover { + background: linear-gradient(135deg, #8bc34a, #cddc39); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.item-desc { + font-size: 13px; + color: #7f8c8d; + line-height: 1.3; + margin-bottom: 8px; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.item-footer { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; +} + +.item-score { + font-size: 14px; + background: linear-gradient(135deg, #8bc34a, #cddc39); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + font-weight: 600; +} + +.item-score-desc { + font-size: 12px; + color: #95a5a6; + margin-left: 4px; +} + +.item-type { + display: flex; + align-items: center; + gap: 4px; +} + +.type-text { + font-size: 12px; + padding: 2px 8px; + border-radius: 10px; + font-weight: 500; + background: linear-gradient(135deg, #f1f8e9, #e8f5e8); + color: #689f38; + border: 1px solid #d4e157; +} + +/* 底部 */ +.footer { + text-align: center; + padding: 24px 0; + border-top: 1px solid #f1f8e9; + margin-top: 32px; +} + +.update-time { + font-size: 12px; + color: #95a5a6; +} + +/* 手机端优化 (默认) */ +@media (max-width: 768px) { + .container { + padding: 0 12px; + } + + .header { + padding: 20px 0; + } + + .title { + font-size: 24px; + } + + .subtitle { + font-size: 13px; + } + + .tv-item { + padding: 14px; + gap: 10px; + } + + .item-cover { + width: 60px; + height: 80px; + } + + .item-title { + font-size: 15px; + } + + .item-desc { + font-size: 12px; + -webkit-line-clamp: 2; + } + + .rank { + width: 28px; + height: 28px; + font-size: 13px; + } +} + +/* 平板端适配 */ +@media (min-width: 769px) and (max-width: 1024px) { + .container { + padding: 0 24px; + } + + .tv-list { + grid-template-columns: repeat(1, 1fr); + gap: 18px; + } + + .title { + font-size: 32px; + } + + .tv-item { + padding: 18px; + } + + .item-cover { + width: 90px; + height: 110px; + } +} + +/* 电脑端适配 */ +@media (min-width: 1025px) { + .container { + padding: 0 32px; + } + + .tv-list { + grid-template-columns: repeat(1, 1fr); + gap: 20px; + } + + .title { + font-size: 36px; + } + + .tv-item { + padding: 20px; + gap: 16px; + } + + .item-cover { + width: 100px; + height: 130px; + } + + .item-title { + font-size: 17px; + } + + .item-desc { + font-size: 14px; + } +} + +/* 大屏幕优化 */ +@media (min-width: 1400px) { + .tv-list { + grid-template-columns: repeat(2, 1fr); + gap: 24px; + } +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/百度电视剧榜/返回接口.json b/InfoGenie-frontend/public/60sapi/热搜榜单/百度电视剧榜/返回接口.json new file mode 100644 index 00000000..8180a103 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/百度电视剧榜/返回接口.json @@ -0,0 +1,276 @@ +{ + "code": 200, + "message": "获取成功。数据来自官方/权威源头,以确保稳定与实时。开源地址 https://github.com/vikiboss/60s,反馈群 595941841", + "data": [ + { + "rank": 1, + "title": "子夜归", + "desc": "改编自扶华的小说《梅夫人宠夫日常》。", + "score": "511898", + "score_desc": "51.19w", + "cover": "https://gips2.baidu.com/it/u=2155452125,2802752464&fm=3028&app=3028&f=JPEG&fmt=auto&q=100&size=f200_266", + "url": "https://www.baidu.com/s?wd=%E5%AD%90%E5%A4%9C%E5%BD%92+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 2, + "title": "献鱼", + "desc": "该剧改编自扶华的小说《向师祖献上咸鱼》,由浙江东阳奔兔影业有限公司备案。主要讲述了多年前,一位高僧曾在庚辰仙府的大魔头师祖司马焦满是血腥杀戮的未来里窥见过一线生机,给他留下一枚佛珠,希望他对生灵有慈心,能将杀心归藏。后来,被“逼上梁山”的廖停雁接受挑战,两手用力直接扯断了红线木珠,依靠咸鱼的本能降服了司马焦,成为改变他的人,也成为了黎民苍生的生机。从此廖停雁开始了引导大魔头向善的任务。", + "score": "334613", + "score_desc": "33.46w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/74230ae3ec03042a352809630060ed6b", + "url": "https://www.baidu.com/s?wd=%E7%8C%AE%E9%B1%BC+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 3, + "title": "锦月如歌", + "desc": "该剧改编自千山茶客的小说《女将星》。", + "score": "261451", + "score_desc": "26.15w", + "cover": "https://gips1.baidu.com/it/u=1353858050,567139191&fm=3028&app=3028&f=JPEG&fmt=auto&q=100&size=f200_266", + "url": "https://www.baidu.com/s?wd=%E9%94%A6%E6%9C%88%E5%A6%82%E6%AD%8C+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 4, + "title": "生万物", + "desc": "天牛庙村首富之女宁绣绣出嫁当天被土匪绑架,父亲宁学祥舍不得卖地赎她,将她的妹妹嫁给她青梅竹马的恋人费文典。绣绣决绝地与父亲断绝了关系,嫁给庄户汉子封大脚,学着干农活并慢慢明白了土地对于农民的意义。受杜春林等人的革命思想的启发,她用所学的知识帮助邻居们,带领村里的妇女一起摆脱封建思想桎梏。她和乡亲们一起除匪患、抗日、拥军,在清苦但又充满传奇的二十年岁月中,绣绣最终和她父亲达成了和解,也实现了自我价值。", + "score": "246220", + "score_desc": "24.62w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/956386852c3948e1539daf2a9e8316c5", + "url": "https://www.baidu.com/s?wd=%E7%94%9F%E4%B8%87%E7%89%A9+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 5, + "title": "归队", + "desc": "故事遵循东北抗联的真实发展轨迹,由小人物视角切入,以小见大的展现了战士们“勇赴国难、自觉担当、顽强苦斗、舍生取义、团结御侮”的东北抗联精神。", + "score": "174373", + "score_desc": "17.44w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/41092aaebdbee0a4a9382c182b913f99", + "url": "https://www.baidu.com/s?wd=%E5%BD%92%E9%98%9F+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 6, + "title": "滤镜", + "desc": "一个新科技产品“滤镜手镯”让普通平凡的苏橙橙(李兰迪 饰)拥有了改变容貌的能力。苏橙橙变成大美女“苏渺”、变成女博士“方谨”、变成撕漫男“全胜唐”,让自己咸鱼翻身爽了一把的同时,帮助弱小伸张正义。与此同时,唐奇(檀健次 饰)对见义勇为的苏渺怦然心动,与志同道合的方谨惺惺相惜,对阳光帅气的全胜唐欣赏称赞。为了保住秘密,苏橙橙不得不一次次撒下弥天大谎,让唐奇一次又一次失去了爱人。唐奇在接连的打击下,眼睛的病情逐渐加重,苏橙橙愧疚心虚。终于,唐奇揭开了苏橙橙变换身份的真相,明白自己爱的只有苏橙橙。真诚炙热的心不会被外在迷惑,心意相通的二人要一起面对滤镜手镯带来的严峻挑战。为了将“千鸟集”培育为独具中国特色的高端美妆品牌,苏橙橙和唐奇携手策划了一系列新的国货美妆产品,号召大家享受“自然自信的真实美”。经历重重考验的苏橙橙最终明白,美不应该被单一固化,要用最真实的自己去面对最现实的生活,依靠努力奋斗去追逐梦想,幸福就在眼前。", + "score": "93122", + "score_desc": "9.31w", + "cover": "https://gips2.baidu.com/it/u=3795500355,4042026657&fm=3028&app=3028&f=JPEG&fmt=auto&q=75&size=f200_266", + "url": "https://www.baidu.com/s?wd=%E6%BB%A4%E9%95%9C+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 7, + "title": "与晋长安", + "desc": "该剧改编自九鹭非香的同名小说。太晋女将军黎霜骁勇善战,她受命在一个月之内找出隐藏的奸细。某日,黎霜偶然间救下身负重伤记忆全失的男子,将其带回军营。男子恳求黎霜收留并跟随她征战。黎霜为其赐名晋安,寓意太晋长治久安。二人合力揪出奸细,却接连遭遇新任监军的蓄意为难和邻国大姚的屡屡犯境,晋安凭借自己过人的智谋与黎霜一起克服困难与险境,二人暗生情愫。晋安逐渐想起自己的真实身份竟是大姚的镇世王,而彼时战事一触即发,二人不得已刀兵相见,本就厌倦战争的二人决定联手化解家国危机,帮助百姓安居乐业。", + "score": "63645", + "score_desc": "6.36w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/f9e7c5bfe847536bca743e3e397b7bff", + "url": "https://www.baidu.com/s?wd=%E4%B8%8E%E6%99%8B%E9%95%BF%E5%AE%89+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 8, + "title": "暗潮缉凶", + "desc": "", + "score": "56675", + "score_desc": "5.67w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/52c73cc7cd55674511becbabd16aca37", + "url": "https://www.baidu.com/s?wd=%E6%9A%97%E6%BD%AE%E7%BC%89%E5%87%B6+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 9, + "title": "深情眼", + "desc": "改编自耳东兔子的同名小说。年过三十的叶蒙遭遇职场不顺,辞职后带着积蓄回到家乡开启惬意的小镇生活,机缘巧合之下,她偶遇了长着一双深情眼的李靳屿,并被他的神秘和冷峻吸引。两个陌生的灵魂不断触碰,叶蒙因李靳屿的艰辛生活而心生怜爱,热情主动地给予帮助;李靳屿也在叶蒙的追求下敞开了心扉,变得自信开朗起来。他们相互温暖、相互治愈,努力经营着这段来之不易的爱情。一枚戒指的到来打破了两人之间的平静,叶蒙母亲多年前患病去世的谜团缓缓浮出水面,叶蒙不得不面对残酷的真相--母亲的离去与李靳屿家有着千丝万缕的联系。此时李靳屿内心的天平早已偏向叶漾,叶蒙给他带来了阳光,现在轮到他来帮助叶蒙解开心结。最终,两人携手揭开上一辈的纠葛,放下过往恩怨,迎接美好的明天。", + "score": "56341", + "score_desc": "5.63w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/f09c4b963cd3cc3062d38e9182be750e", + "url": "https://www.baidu.com/s?wd=%E6%B7%B1%E6%83%85%E7%9C%BC+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 10, + "title": "定风波", + "desc": "《定风波》聚焦宋韵文化传承传播,围绕诗文、书画、美食、旅游、民生等主题,多维度描绘苏东坡的为官之道、志趣审美和精神世界,深入解读苏东坡的当代价值。全片共5集,每集50分钟。第一集“出川记”讲述苏东坡的成长与家风,建构其人生起始动力,探索其后来到杭州的动因;第二集“湖山记”讲述苏东坡首次为官杭州,受到湖山的滋养,实现真正的“胸有丘壑”;第三集“摩羯记”讲述苏东坡应对乌台诗案带来的种种影响,以乐观精神渡过人生的劫难;第四集“悬壶记”讲述苏东坡二度为官杭州,负责防疫,建安乐坊以及重新治理西湖;第五集“筑巢记”讲述苏东坡济苍生、度余生,保持“此心安处是吾乡”的人生态度。", + "score": "51095", + "score_desc": "5.11w", + "cover": "https://gips0.baidu.com/it/u=2177619972,3043234332&fm=3028&app=3028&f=JPEG&fmt=auto&q=100&size=f200_266", + "url": "https://www.baidu.com/s?wd=%E5%AE%9A%E9%A3%8E%E6%B3%A2+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 11, + "title": "白月梵星", + "desc": "本剧改编自星零小说《白烁上神》,讲述将军府嫡女白烁为报恩而立志修仙,寻仙途中意外搭救妖族大神梵樾,二人不打不相识,从相互利用到互生爱意、双向奔赴,纵然隔着千重困难,但爱足以打破一切限制,拥抱最真的彼此的故事。", + "score": "44201", + "score_desc": "4.42w", + "cover": "https://gips3.baidu.com/it/u=1404661215,4211295377&fm=3028&app=3028&f=JPEG&fmt=auto&q=75&size=f200_266", + "url": "https://www.baidu.com/s?wd=%E7%99%BD%E6%9C%88%E6%A2%B5%E6%98%9F+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 12, + "title": "我在顶峰等你", + "desc": "上一世,顾雪茭曾因恋爱脑而高考失利,职场打拼多年,归来仍是底层外包人员,还首当其冲地成为了“黑心老板”蔺之华的裁员目标。顾雪茭找蔺之华理论,意外重生回到高三那年。有机会重新开局,顾雪茭吸取前世教训,痛定思痛,将学习作为人生第一要务,由恋爱脑扭转为事业脑,在爆改人生的同时,还共同成就一段双向奔赴、互为变量的甜美爱情。", + "score": "37003", + "score_desc": "3.7w", + "cover": "https://gips2.baidu.com/it/u=3240531593,2885940403&fm=3028&app=3028&f=JPEG&fmt=auto&q=100&size=f200_266", + "url": "https://www.baidu.com/s?wd=%E6%88%91%E5%9C%A8%E9%A1%B6%E5%B3%B0%E7%AD%89%E4%BD%A0+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 13, + "title": "六姊妹", + "desc": "本剧改编自豆瓣阅读连载小说《六姊妹》,作者伊北。新中国成立后,何常胜为支援社会主义建设,携家带口从扬州江都移居安徽淮南,在淮河边上扎下了根。在接下来的二十年中,何常胜连得六个女儿,却在一场车祸中告别人世。大姐何家丽和奶奶何文氏、妈妈刘美心一起承担起了家庭重担,安顿妹妹们成家立业。时代在变化,何家六姊妹也经历了婚恋、工 作、生活等命运起伏,但她们团结一心,共同面对人生的风雨,在生活的磨砺中,六姊妹们也终于明白父亲生前反复强调的“家”的意义。", + "score": "36574", + "score_desc": "3.66w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/9e517a4f66e7fb7106b6333b85f1a5c1", + "url": "https://www.baidu.com/s?wd=%E5%85%AD%E5%A7%8A%E5%A6%B9+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 14, + "title": "扫毒风暴", + "desc": "1995年,缉毒警林强峰(段奕宏 饰)为了追查毒品的线索调到了西港缉毒支队工作。走私商刘少华(秦昊 饰)因偶然的机会接触到了冰毒,毒品带来的巨大利润让他产生邪念,成为了一名制毒师。在林强峰等缉毒警的全力追查下,西港市的涉案的毒贩们一一落网,只剩刘少华在别处鼠窜,企图躲避警方追捕。 1996年,林强峰再次查没了企图东山再起的刘少华的毒品,走投无路的刘少华只能蛰伏了起来,之后刘少华企图再次制毒,被林强峰发现踪迹。1999年,刘少华终于落网。", + "score": "32911", + "score_desc": "3.29w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/d9e3d21ca332652ffe75d7176bce397f", + "url": "https://www.baidu.com/s?wd=%E6%89%AB%E6%AF%92%E9%A3%8E%E6%9A%B4+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 15, + "title": "目之所及", + "desc": "本剧改编自阅读连载小说《盲目》,作者慕遥而寻。 世纪之交,因为水利工程的蓄水要求,一座江边小城即将被淹没,人们如火如荼地进行着新城的规划建设和人口的迁徙。此时,一桩离奇的杀夫案闯入了警方的视野,嫌疑人中,一个是咬定丈夫杀了女儿的可怜女人曲桐,一个是按摩院身份模糊的盲人薛小伟, 他们相互救赎,甘愿为对方牺牲,疑点重重。警 方锲而不舍的追查,揭秘出一段尘封多年,令人唏嘘的往事。真相可能会被淹没,但终有浮出水面的一天。", + "score": "27439", + "score_desc": "2.74w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/3b731c9a9e809e7c694a8cc5c65d5a15", + "url": "https://www.baidu.com/s?wd=%E7%9B%AE%E4%B9%8B%E6%89%80%E5%8F%8A+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 16, + "title": "书卷一梦", + "desc": "柠萌影业出品,改编自千山茶客的同名小说,尚书府嫡长女蒋阮被当成一枚棋子送入宫中,爱上温文儒雅的八皇子。谁知一朝宫变,爱人登基,府上鸡犬升天,她却成为一枚弃子,被污蔑为祸国妖女。蒋阮不甘,下定决心要报仇,却在回府之时遭遇暗杀,后借助神秘黑衣人之手才逃过一劫。从危机四伏的宅院到步步惊心的朝堂,她面对的敌人越来越多她暗暗布下陷阱,却误打误撞遇到锦英王萧韶。萧韶性情冷清,却屡次出手相助于她,两人暗生情愫,渐渐结盟,萧韶的身世之谜也随之浮出水面。此后,蒋阮千方百计阻挠八皇子的夺嫡大业,却引起了萧韶的怀疑,两人结下误会八皇子开始进行疯狂的反击行动,蒋阮的处境十分危险。复仇途中,蒋阮发现自己的身世竟和萧韶的身世之谜有关,一个大锦朝隐藏多年的秘密浮出水面此时,南疆人蠢蠢欲动,欲与宣离结为同盟。彼时,蒋阮小时候被继母种下的毒发作,萧韶带她四处求医,生死一线的时候,蒋阮得知了一个更大的秘密", + "score": "26702", + "score_desc": "2.67w", + "cover": "https://gips2.baidu.com/it/u=1593831522,852391480&fm=3028&app=3028&f=JPEG&fmt=auto&q=100&size=f200_266", + "url": "https://www.baidu.com/s?wd=%E4%B9%A6%E5%8D%B7%E4%B8%80%E6%A2%A6+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 17, + "title": "樱桃琥珀", + "desc": "《樱桃琥珀》要被影视化了,温柔女主学霸男主,主人公从小城到大都市,直至婚姻殿堂的女孩成长故事,由国内一线知名影视公司出品。", + "score": "26660", + "score_desc": "2.67w", + "cover": "https://gips3.baidu.com/it/u=2643705168,575328711&fm=3028&app=3028&f=JPEG&fmt=auto&q=100&size=f200_266", + "url": "https://www.baidu.com/s?wd=%E6%A8%B1%E6%A1%83%E7%90%A5%E7%8F%80+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 18, + "title": "咒术回战第二季", + "desc": "", + "score": "26617", + "score_desc": "2.66w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/7b3cfcaf3b343d45f5c16f3e47a9f946", + "url": "https://www.baidu.com/s?wd=%E5%92%92%E6%9C%AF%E5%9B%9E%E6%88%98%E7%AC%AC%E4%BA%8C%E5%AD%A3+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 19, + "title": "偷偷藏不住", + "desc": "桑稚高中时期被老师频繁请家长,为了解决麻烦,桑稚决定找哥哥顶包,然而兄妹见面就互怼闹僵,无奈只好求助来家中玩耍的哥哥舍友段嘉许,在桑稚的苦求要挟下,段嘉许帮桑稚去学校见老师,两人因此结缘,段嘉许从此更是把桑稚当成自己的亲妹妹爱护。随着段嘉许大学毕业,两人分隔异地,又因为一些误会,关系疏远。直到成年后的桑稚如愿考到了段嘉许的城市,两人重逢。在日渐亲密的接触下,桑稚渐渐发现了段嘉许一直以来的压力来源,她想要保护这个一直对自己很好的大哥哥,重拾埋藏心底的暗恋。在桑稚的陪伴下,段嘉许慢慢解开心结,他真心喜欢上了长大的桑稚,一段纯真暗恋终于开出美丽的爱情花朵。", + "score": "24655", + "score_desc": "2.47w", + "cover": "https://gips3.baidu.com/it/u=2216037055,3672846777&fm=3028&app=3028&f=JPEG&fmt=auto&q=75&size=f200_266", + "url": "https://www.baidu.com/s?wd=%E5%81%B7%E5%81%B7%E8%97%8F%E4%B8%8D%E4%BD%8F+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 20, + "title": "一路朝阳", + "desc": "北漂女孩李慕嘉毕业后进入北京最知名的律所,靠着自己的勤奋努力从行政助理一路成为独当一面的律师,在职业巅峰切换跑道加入创业公司,大起大落最终创业成功,收获了一个家;闺蜜田蓉毕业求职未果,误打误撞成为房产中介,与北京男孩李万兵仓促结婚,在婚后职业和感情都遭受了巨大考验;表妹陈青斯坦福毕业与男友回国创业,遭遇种种挫折但找到了心之所向。从2007到2019年,三个女孩对人生的追求和希望在现实中身不由己地改变了模样,庆幸的是十年的磨砺最终还是求得了人生的向阳面,得以一路朝阳。", + "score": "24482", + "score_desc": "2.45w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/356088680f3a962380c8d700cf9a2826", + "url": "https://www.baidu.com/s?wd=%E4%B8%80%E8%B7%AF%E6%9C%9D%E9%98%B3+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 21, + "title": "她和她的他们", + "desc": "《她和她的他们》是由徐麒丰担任总导演、王兵导演,由肖顺尧、贾青、何杜娟领衔主演,胡军特邀领衔主演,袁家欢、王大奇、蒋方婷、郑家彬、钟林煜、李琦、秦奋等主演的都市犯罪悬疑剧。该剧讲述了刑警队副队长赵熵与搭档崔山河,抽丝剥茧,一层层揭开七人之间错综复杂的情感秘密,一场场关于人性、伦理的纠葛,一出出谎言交织的虐戏逐步上演。随着真相步步逼近,赵熵也拉开了自我救赎的序幕。", + "score": "24375", + "score_desc": "2.44w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/6b5d1065fb78498ab26d77cd0e0c7c27", + "url": "https://www.baidu.com/s?wd=%E5%A5%B9%E5%92%8C%E5%A5%B9%E7%9A%84%E4%BB%96%E4%BB%AC+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 22, + "title": "卿卿日常", + "desc": "《清穿日常》是多木木多所著网络小说,在晋江文学城、中国移动和阅读等网站连载。吃……吃喝喝那些事。反正清穿已经都穿成筛子了。清穿就是为了遇见阿哥,种种田过过日子!今天,你清穿了吗?", + "score": "22800", + "score_desc": "2.28w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/6caa4eb1bb38d643d7099b060d94acee", + "url": "https://www.baidu.com/s?wd=%E5%8D%BF%E5%8D%BF%E6%97%A5%E5%B8%B8+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 23, + "title": "初恋,稍显粗糙", + "desc": "《初恋,稍显粗糙》是由小野花梨、风间俊介主演的电视剧,于2023年7月7日在东京电视台深夜播出。该剧改编自作者ざくざくろ的同名漫画,讲述一位轻度智力障碍女性的纯爱故事。", + "score": "21904", + "score_desc": "2.19w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/e4c672a71dfa478102360895a77b4108", + "url": "https://www.baidu.com/s?wd=%E5%88%9D%E6%81%8B%EF%BC%8C%E7%A8%8D%E6%98%BE%E7%B2%97%E7%B3%99+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 24, + "title": "九重紫", + "desc": "年少失母的窦昭因为家庭变故和坎坷波折的命运对人间情爱与亲情失望透顶,她斗继母、保家产,避居冷僻田庄,求学晓事以图自保自强。大雨之夜,窦昭与扮作商贾投宿的宋墨在田庄相逢,用自己的智慧帮其保下平寇有功的定国公一脉遗孤,二人命运也因此紧紧缠绕。出身官宦之家的宋墨深陷家变谜团,而窦昭也在继母的破坏下遭遇换亲流言,二人选择成亲以结同盟、共度困局。曾经彼此猜忌的他们在相互帮扶中共渡难关,也由此渐渐相知相惜、互为知己。不料风雨欲来、朝堂骤变,窦昭与宋墨携手面对危局,共同挽救家族命运、解开英国公府换子疑云、成功阻止辽王谋逆,平忠臣冤案、保家国安宁,活出了真正属于自己的幸福生活。", + "score": "21717", + "score_desc": "2.17w", + "cover": "https://gips3.baidu.com/it/u=1237661084,451511578&fm=3028&app=3028&f=JPEG&fmt=auto&q=75&size=f200_266", + "url": "https://www.baidu.com/s?wd=%E4%B9%9D%E9%87%8D%E7%B4%AB+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 25, + "title": "香港人在北京", + "desc": "《香港人在北京》是由陈展鹏、吴若希、戴祖仪主演的TVB电视剧,在拍摄中。", + "score": "21238", + "score_desc": "2.12w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/2e5f4d3fe3b36a7d9f4f782c35979016", + "url": "https://www.baidu.com/s?wd=%E9%A6%99%E6%B8%AF%E4%BA%BA%E5%9C%A8%E5%8C%97%E4%BA%AC+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 26, + "title": "你好,我们是欢喜天团", + "desc": "《你好,我们是欢喜天团》是由刘浩南执导,由王艺瑾、千喆、高卿尘领衔主演,易恒、伍雅露、阿克朱力、曹左、贵尚奇、庄逸涵、曲梦婷主演,陈名豪、代少冬特别出演的古代网络微短剧。2022年10月15日,《你好,我们是欢喜天团》杀青。该剧于2023年9月22日在腾讯视频播出。", + "score": "20966", + "score_desc": "2.1w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/94e45c218022c97e865f68c3a15c9c22", + "url": "https://www.baidu.com/s?wd=%E4%BD%A0%E5%A5%BD%EF%BC%8C%E6%88%91%E4%BB%AC%E6%98%AF%E6%AC%A2%E5%96%9C%E5%A4%A9%E5%9B%A2+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 27, + "title": "诛仙", + "desc": "一夜间惨变孤儿的张小凡被青云门收为弟子,经过五年刻苦修炼,他在师门七脉会武上大放异彩,后被派往空桑山打探魔教行迹,旅程中,他与师姐陆雪琪遭遇危难,并结识救护了魔教女子碧瑶,同时,新的危险也在前方等待着他。", + "score": "20659", + "score_desc": "2.07w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/ab55434dff2e8c4432119fc980f5a51d", + "url": "https://www.baidu.com/s?wd=%E8%AF%9B%E4%BB%99+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 28, + "title": "玫瑰的故事", + "desc": "电视剧改编自亦舒同名小说,由刘亦菲出演该剧女一号。剧中主要讲述了黄玫瑰一生的情感故事。出身于富贵之家的玫瑰经历了几段刻骨铭心的爱情,在浮浮沉沉中明白自己想要的是什么,为爱放手去追寻,成长为更有勇气的自己。", + "score": "20439", + "score_desc": "2.04w", + "cover": "https://gips1.baidu.com/it/u=1227308879,4121027510&fm=3028&app=3028&f=PNG&fmt=auto&q=75&size=f608_864", + "url": "https://www.baidu.com/s?wd=%E7%8E%AB%E7%91%B0%E7%9A%84%E6%95%85%E4%BA%8B+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 29, + "title": "爱你,是我做过最好的事", + "desc": "《爱你,是我做过最好的事》笙离的小说。讲述了一个关于青春、成长、初恋、选择的故事。", + "score": "20196", + "score_desc": "2.02w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/d680ad814edfef5438f7e6175c0456f6", + "url": "https://www.baidu.com/s?wd=%E7%88%B1%E4%BD%A0%EF%BC%8C%E6%98%AF%E6%88%91%E5%81%9A%E8%BF%87%E6%9C%80%E5%A5%BD%E7%9A%84%E4%BA%8B+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + }, + { + "rank": 30, + "title": "唐朝诡事录", + "desc": "暗夜邪仙从天而降,鬼市地宫露出冰山一角,而风靡长安的诡异红茶究竟是养生之药还是害人之物?长安城里新娘失踪案接连发生,似乎与红茶有着千丝万缕的联系案件扑朔迷离,人心玄妙难鉴!金吾卫中郎将卢凌风奉命查案,遭遇平生最强对手狄仁杰关门弟子苏无名,双强携手共破长安奇案!九个不同风格的诡异案件,《长安红茶》《石桥图》《众生堂》《黄梅杀》《甘棠驿怪谈》《鼍神》《人面花》《参天楼》,一一为您揭晓大唐夜色笼罩之下的奇闻异录! 见证唐诗之外,被湮没千年的奇诡想象。千年前的唐朝,万邦来朝,是当之无愧的世界中心。优越的物质生活,多样的文化融合,催生了唐朝人极致的想象力。 除了李白、杜甫、白居易等一代传奇诗人,用唐诗描绘出的华丽的大唐美卷;市井间的贩夫走卒,更用他们更加不羁的想象力,在唐朝的夜幕中 勾勒出神魔鬼怪的憧憧魅影:仙魔精妖、奇闻怪谈、幻术道法、异域传说、珍禽异兽、宫廷轶事", + "score": "17785", + "score_desc": "1.78w", + "cover": "https://fyb-2.cdn.bcebos.com/hotboard_image/5bb62453122a1d67e077b70321676175", + "url": "https://www.baidu.com/s?wd=%E5%94%90%E6%9C%9D%E8%AF%A1%E4%BA%8B%E5%BD%95+%E7%94%B5%E8%A7%86%E5%89%A7&sa=fyb_teleplay_all_all&rsv_dl=fyb_teleplay_all_all" + } + ] +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/api.js b/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/api.js new file mode 100644 index 00000000..46def0f0 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/api.js @@ -0,0 +1,146 @@ +// API 配置和数据获取模块 +class HotTopicsAPI { + constructor() { + this.apiUrl = 'https://60s.api.shumengya.top/v2/baidu/tieba'; + this.fallbackData = null; + } + + // 获取热搜数据 + async fetchHotTopics() { + try { + const response = await fetch(this.apiUrl, { + method: 'GET', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + // 添加超时控制 + signal: AbortSignal.timeout(10000) // 10秒超时 + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + + // 验证数据格式 + if (!this.validateData(data)) { + throw new Error('Invalid data format'); + } + + // 缓存成功的数据作为备用 + this.fallbackData = data; + + return { + success: true, + data: data, + timestamp: new Date().toISOString() + }; + } catch (error) { + console.error('API请求失败:', error); + + // 如果有缓存数据,返回缓存数据 + if (this.fallbackData) { + return { + success: true, + data: this.fallbackData, + timestamp: new Date().toISOString(), + isCache: true + }; + } + + return { + success: false, + error: error.message, + timestamp: new Date().toISOString() + }; + } + } + + // 验证数据格式 + validateData(data) { + if (!data || typeof data !== 'object') { + return false; + } + + if (data.code !== 200) { + return false; + } + + if (!Array.isArray(data.data)) { + return false; + } + + // 验证数据项格式 + return data.data.every(item => { + return item.rank && + item.title && + item.desc && + item.score_desc; + }); + } + + // 处理图片URL + processImageUrl(url) { + if (!url) return null; + + // 处理百度贴吧图片URL的特殊字符 + try { + return url.replace(/&/g, '&'); + } catch (error) { + console.warn('图片URL处理失败:', error); + return null; + } + } + + // 处理跳转URL + processTopicUrl(url) { + if (!url) return '#'; + + try { + return url.replace(/&/g, '&'); + } catch (error) { + console.warn('链接URL处理失败:', error); + return '#'; + } + } + + // 格式化分数显示 + formatScore(score, scoreDesc) { + if (scoreDesc) { + return scoreDesc; + } + + if (typeof score === 'number') { + if (score >= 10000) { + return (score / 10000).toFixed(1) + 'w'; + } + return score.toString(); + } + + return '0'; + } + + // 截断文本 + truncateText(text, maxLength = 100) { + if (!text) return ''; + + if (text.length <= maxLength) { + return text; + } + + return text.substring(0, maxLength) + '...'; + } + + // 获取排名样式类 + getRankClass(rank) { + if (rank === 1) return 'top-1'; + if (rank === 2) return 'top-2'; + if (rank === 3) return 'top-3'; + return 'normal'; + } +} + +// 导出API实例 +const hotTopicsAPI = new HotTopicsAPI(); \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/app.js b/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/app.js new file mode 100644 index 00000000..7c31b50e --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/app.js @@ -0,0 +1,201 @@ +// 主应用程序文件 +class HotTopicsApp { + constructor() { + this.isInitialized = false; + this.retryCount = 0; + this.maxRetries = 3; + this.retryDelay = 2000; // 2秒 + } + + // 初始化应用 + async init() { + if (this.isInitialized) return; + + try { + console.log('初始化百度贴吧热搜应用...'); + + // 检查必要的元素是否存在 + this.checkRequiredElements(); + + // 加载初始数据 + await this.loadHotTopics(); + + // 设置自动刷新 + this.setupAutoRefresh(); + + // 设置页面可见性监听 + this.setupVisibilityListener(); + + this.isInitialized = true; + console.log('应用初始化完成'); + + } catch (error) { + console.error('应用初始化失败:', error); + uiManager.showError('应用初始化失败,请刷新页面重试'); + } + } + + // 检查必要元素 + checkRequiredElements() { + const requiredElements = ['loading', 'error', 'hotList', 'refreshBtn', 'updateTime']; + const missingElements = requiredElements.filter(id => !document.getElementById(id)); + + if (missingElements.length > 0) { + throw new Error(`缺少必要元素: ${missingElements.join(', ')}`); + } + } + + // 加载热搜数据 + async loadHotTopics() { + try { + console.log('开始获取热搜数据...'); + uiManager.showLoading(); + + const result = await hotTopicsAPI.fetchHotTopics(); + + if (result.success) { + console.log('数据获取成功:', result.data.data?.length || 0, '条记录'); + uiManager.renderHotTopics(result.data); + this.retryCount = 0; // 重置重试计数 + + // 如果是缓存数据,显示提示 + if (result.isCache) { + uiManager.showToast('当前显示缓存数据', 3000); + } + } else { + throw new Error(result.error || '数据获取失败'); + } + + } catch (error) { + console.error('加载热搜数据失败:', error); + + // 重试逻辑 + if (this.retryCount < this.maxRetries) { + this.retryCount++; + console.log(`第 ${this.retryCount} 次重试...`); + + uiManager.showToast(`加载失败,${this.retryDelay / 1000}秒后重试...`, this.retryDelay); + + setTimeout(() => { + this.loadHotTopics(); + }, this.retryDelay); + + // 增加重试延迟 + this.retryDelay = Math.min(this.retryDelay * 1.5, 10000); + } else { + uiManager.showError('数据加载失败,请检查网络连接后重试'); + this.retryCount = 0; + this.retryDelay = 2000; + } + } + } + + // 设置自动刷新 + setupAutoRefresh() { + // 每5分钟自动刷新一次 + setInterval(() => { + if (document.visibilityState === 'visible' && !uiManager.isLoading) { + console.log('自动刷新数据...'); + this.loadHotTopics(); + } + }, 5 * 60 * 1000); // 5分钟 + } + + // 设置页面可见性监听 + setupVisibilityListener() { + document.addEventListener('visibilitychange', () => { + if (document.visibilityState === 'visible') { + // 页面变为可见时,检查是否需要刷新数据 + const lastUpdate = localStorage.getItem('lastUpdateTime'); + const now = Date.now(); + + if (!lastUpdate || (now - parseInt(lastUpdate)) > 10 * 60 * 1000) { + // 超过10分钟没更新,自动刷新 + console.log('页面重新可见,刷新数据...'); + this.loadHotTopics(); + } + } + }); + } + + // 手动刷新 + async refresh() { + if (uiManager.isLoading) { + console.log('正在加载中,忽略刷新请求'); + return; + } + + console.log('手动刷新数据...'); + this.retryCount = 0; + this.retryDelay = 2000; + await this.loadHotTopics(); + } + + // 获取应用状态 + getStatus() { + return { + isInitialized: this.isInitialized, + isLoading: uiManager.isLoading, + retryCount: this.retryCount, + lastUpdate: localStorage.getItem('lastUpdateTime') + }; + } +} + +// 创建应用实例 +const app = new HotTopicsApp(); + +// 全局函数,供HTML调用 +window.loadHotTopics = () => app.loadHotTopics(); +window.refreshData = () => app.refresh(); +window.getAppStatus = () => app.getStatus(); + +// 页面加载完成后初始化 +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => { + app.init(); + }); +} else { + // 如果页面已经加载完成 + app.init(); +} + +// 错误处理 +window.addEventListener('error', (event) => { + console.error('全局错误:', event.error); + + // 如果是网络错误,显示友好提示 + if (event.error?.message?.includes('fetch') || + event.error?.message?.includes('network') || + event.error?.message?.includes('Failed to fetch')) { + uiManager.showToast('网络连接异常,请检查网络设置'); + } +}); + +// 未处理的Promise拒绝 +window.addEventListener('unhandledrejection', (event) => { + console.error('未处理的Promise拒绝:', event.reason); + + // 防止默认的错误处理 + event.preventDefault(); + + // 显示用户友好的错误信息 + if (event.reason?.message?.includes('fetch') || + event.reason?.message?.includes('network')) { + uiManager.showToast('网络请求失败,请稍后重试'); + } +}); + +// 导出应用实例(用于调试) +window.hotTopicsApp = app; + +// 开发模式下的调试信息 +if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') { + console.log('🚀 百度贴吧热搜应用已启动'); + console.log('📱 响应式设计已启用'); + console.log('🔄 自动刷新已设置(5分钟间隔)'); + console.log('💡 可用调试命令:'); + console.log(' - hotTopicsApp.getStatus() // 获取应用状态'); + console.log(' - hotTopicsApp.refresh() // 手动刷新'); + console.log(' - loadHotTopics() // 重新加载数据'); +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/index.html b/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/index.html new file mode 100644 index 00000000..3e06b890 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/index.html @@ -0,0 +1,57 @@ + + + + + + 百度贴吧热搜榜单 + + + + + +
+ +
+
+ +
+ +
+
+
+ + +
+
+

正在获取最新热搜...

+
+ + + + + +
+
+ +
+
+ + +
+

最后更新:--

+

数据来源:百度贴吧官方

+
+
+ + + + + + \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/styles.css b/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/styles.css new file mode 100644 index 00000000..4d7622e6 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/styles.css @@ -0,0 +1,419 @@ +/* 全局样式重置 */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + background: linear-gradient(135deg, #e8f5e8 0%, #f9f9e8 50%, #f5f5f5 100%); + min-height: 100vh; + color: #333; + line-height: 1.6; +} + +.container { + max-width: 800px; + margin: 0 auto; + padding: 0 16px; + min-height: 100vh; + display: flex; + flex-direction: column; +} + +/* 头部样式 */ +.header { + padding: 20px 0; + position: sticky; + top: 0; + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + border-radius: 0 0 20px 20px; + margin-bottom: 20px; + z-index: 100; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); +} + +.header-content { + display: flex; + justify-content: space-between; + align-items: center; +} + +.logo { + display: flex; + align-items: center; + gap: 12px; +} + +.logo i { + font-size: 28px; + color: #7fb069; +} + +.logo h1 { + font-size: 24px; + font-weight: 700; + color: #2d3748; + margin: 0; +} + +.refresh-btn { + width: 44px; + height: 44px; + border-radius: 50%; + background: linear-gradient(135deg, #7fb069, #a8cc8c); + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 4px 15px rgba(127, 176, 105, 0.3); +} + +.refresh-btn:hover { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(127, 176, 105, 0.4); +} + +.refresh-btn:active { + transform: translateY(0); +} + +.refresh-btn i { + color: white; + font-size: 18px; +} + +.refresh-btn.loading i { + animation: spin 1s linear infinite; +} + +@keyframes spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +/* 主内容区域 */ +.main-content { + flex: 1; + margin-bottom: 20px; +} + +/* 加载状态 */ +.loading { + text-align: center; + padding: 60px 20px; + color: white; +} + +.loading-spinner { + width: 40px; + height: 40px; + border: 3px solid rgba(255, 255, 255, 0.3); + border-top: 3px solid white; + border-radius: 50%; + margin: 0 auto 20px; + animation: spin 1s linear infinite; +} + +.loading p { + font-size: 16px; + opacity: 0.9; +} + +/* 错误状态 */ +.error { + text-align: center; + padding: 60px 20px; + color: white; +} + +.error i { + font-size: 48px; + margin-bottom: 20px; + opacity: 0.8; +} + +.error p { + font-size: 16px; + margin-bottom: 20px; + opacity: 0.9; +} + +.retry-btn { + background: rgba(255, 255, 255, 0.2); + border: 2px solid rgba(255, 255, 255, 0.3); + color: white; + padding: 12px 24px; + border-radius: 25px; + cursor: pointer; + font-size: 14px; + transition: all 0.3s ease; +} + +.retry-btn:hover { + background: rgba(255, 255, 255, 0.3); + border-color: rgba(255, 255, 255, 0.5); +} + +/* 热搜列表 */ +.hot-list { + display: grid; + gap: 16px; +} + +.hot-item { + background: rgba(255, 255, 255, 0.95); + border-radius: 16px; + padding: 20px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); + transition: all 0.3s ease; + cursor: pointer; + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.2); +} + +.hot-item:hover { + transform: translateY(-4px); + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15); + background: rgba(255, 255, 255, 1); +} + +.hot-item-header { + display: flex; + align-items: flex-start; + gap: 16px; + margin-bottom: 12px; +} + +.rank-badge { + min-width: 32px; + height: 32px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + font-size: 14px; + color: white; + flex-shrink: 0; +} + +.rank-badge.top-1 { + background: linear-gradient(135deg, #ff6b6b, #ee5a24); + box-shadow: 0 4px 15px rgba(255, 107, 107, 0.3); +} + +.rank-badge.top-2 { + background: linear-gradient(135deg, #ffa726, #ff7043); + box-shadow: 0 4px 15px rgba(255, 167, 38, 0.3); +} + +.rank-badge.top-3 { + background: linear-gradient(135deg, #ffca28, #ffa000); + box-shadow: 0 4px 15px rgba(255, 202, 40, 0.3); +} + +.rank-badge.normal { + background: linear-gradient(135deg, #7fb069, #a8cc8c); + box-shadow: 0 4px 15px rgba(127, 176, 105, 0.3); +} + +.hot-item-content { + flex: 1; + min-width: 0; +} + +.hot-title { + font-size: 16px; + font-weight: 600; + color: #2d3748; + margin-bottom: 8px; + line-height: 1.4; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.hot-desc { + font-size: 14px; + color: #718096; + line-height: 1.5; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + margin-bottom: 12px; +} + +.hot-meta { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.hot-score { + display: flex; + align-items: center; + gap: 6px; + color: #7fb069; + font-weight: 600; + font-size: 14px; +} + +.hot-score i { + font-size: 12px; +} + +.hot-avatar { + width: 24px; + height: 24px; + border-radius: 50%; + object-fit: cover; + border: 2px solid rgba(127, 176, 105, 0.2); +} + +/* 底部 */ +.footer { + text-align: center; + padding: 20px 0; + color: rgba(255, 255, 255, 0.8); + font-size: 12px; + line-height: 1.5; +} + +.update-time { + margin-bottom: 4px; + font-weight: 500; +} + +.data-source { + opacity: 0.7; +} + +/* 响应式设计 */ +@media (max-width: 768px) { + .container { + padding: 0 12px; + } + + .header { + padding: 16px 0; + margin-bottom: 16px; + } + + .logo h1 { + font-size: 20px; + } + + .logo i { + font-size: 24px; + } + + .refresh-btn { + width: 40px; + height: 40px; + } + + .refresh-btn i { + font-size: 16px; + } + + .hot-list { + gap: 12px; + } + + .hot-item { + padding: 16px; + } + + .hot-item-header { + gap: 12px; + margin-bottom: 10px; + } + + .rank-badge { + min-width: 28px; + height: 28px; + font-size: 12px; + } + + .hot-title { + font-size: 15px; + } + + .hot-desc { + font-size: 13px; + } + + .hot-score { + font-size: 13px; + } + + .hot-avatar { + width: 20px; + height: 20px; + border: 2px solid rgba(127, 176, 105, 0.2); + } +} + +@media (max-width: 480px) { + .container { + padding: 0 8px; + } + + .hot-item { + padding: 12px; + } + + .hot-title { + font-size: 14px; + } + + .hot-desc { + font-size: 12px; + } +} + +/* 动画效果 */ +.hot-item { + animation: fadeInUp 0.6s ease forwards; + opacity: 0; + transform: translateY(20px); +} + +.hot-item:nth-child(1) { animation-delay: 0.1s; } +.hot-item:nth-child(2) { animation-delay: 0.2s; } +.hot-item:nth-child(3) { animation-delay: 0.3s; } +.hot-item:nth-child(4) { animation-delay: 0.4s; } +.hot-item:nth-child(5) { animation-delay: 0.5s; } +.hot-item:nth-child(n+6) { animation-delay: 0.6s; } + +@keyframes fadeInUp { + to { + opacity: 1; + transform: translateY(0); + } +} + +/* 滚动条样式 */ +::-webkit-scrollbar { + width: 6px; +} + +::-webkit-scrollbar-track { + background: rgba(255, 255, 255, 0.1); +} + +::-webkit-scrollbar-thumb { + background: rgba(255, 255, 255, 0.3); + border-radius: 3px; +} + +::-webkit-scrollbar-thumb:hover { + background: rgba(255, 255, 255, 0.5); +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/ui.js b/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/ui.js new file mode 100644 index 00000000..89f01bb3 --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/ui.js @@ -0,0 +1,354 @@ +// UI 渲染和交互模块 +class UIManager { + constructor() { + this.elements = { + loading: document.getElementById('loading'), + error: document.getElementById('error'), + hotList: document.getElementById('hotList'), + refreshBtn: document.getElementById('refreshBtn'), + updateTime: document.getElementById('updateTime') + }; + + this.isLoading = false; + this.initEventListeners(); + } + + // 初始化事件监听器 + initEventListeners() { + // 刷新按钮点击事件 + this.elements.refreshBtn.addEventListener('click', () => { + if (!this.isLoading) { + this.refreshData(); + } + }); + + // 键盘快捷键 + document.addEventListener('keydown', (e) => { + if (e.key === 'F5' || (e.ctrlKey && e.key === 'r')) { + e.preventDefault(); + if (!this.isLoading) { + this.refreshData(); + } + } + }); + + // 下拉刷新(移动端) + this.initPullToRefresh(); + } + + // 初始化下拉刷新 + initPullToRefresh() { + let startY = 0; + let currentY = 0; + let isPulling = false; + const threshold = 80; + + document.addEventListener('touchstart', (e) => { + if (window.scrollY === 0) { + startY = e.touches[0].clientY; + isPulling = true; + } + }); + + document.addEventListener('touchmove', (e) => { + if (isPulling && window.scrollY === 0) { + currentY = e.touches[0].clientY; + const pullDistance = currentY - startY; + + if (pullDistance > 0) { + e.preventDefault(); + + // 添加视觉反馈 + if (pullDistance > threshold) { + this.elements.refreshBtn.style.transform = 'scale(1.1)'; + } else { + this.elements.refreshBtn.style.transform = 'scale(1)'; + } + } + } + }); + + document.addEventListener('touchend', () => { + if (isPulling) { + const pullDistance = currentY - startY; + + if (pullDistance > threshold && !this.isLoading) { + this.refreshData(); + } + + this.elements.refreshBtn.style.transform = 'scale(1)'; + isPulling = false; + } + }); + } + + // 显示加载状态 + showLoading() { + this.isLoading = true; + this.elements.loading.style.display = 'block'; + this.elements.error.style.display = 'none'; + this.elements.hotList.style.display = 'none'; + this.elements.refreshBtn.classList.add('loading'); + } + + // 隐藏加载状态 + hideLoading() { + this.isLoading = false; + this.elements.loading.style.display = 'none'; + this.elements.refreshBtn.classList.remove('loading'); + } + + // 显示错误状态 + showError(message = '获取数据失败,请稍后重试') { + this.hideLoading(); + this.elements.error.style.display = 'block'; + this.elements.hotList.style.display = 'none'; + + const errorText = this.elements.error.querySelector('p'); + if (errorText) { + errorText.textContent = message; + } + } + + // 显示热搜列表 + showHotList() { + this.hideLoading(); + this.elements.error.style.display = 'none'; + this.elements.hotList.style.display = 'grid'; + } + + // 渲染热搜数据 + renderHotTopics(data) { + if (!data || !data.data || !Array.isArray(data.data)) { + this.showError('数据格式错误'); + return; + } + + const hotTopics = data.data; + this.elements.hotList.innerHTML = ''; + + hotTopics.forEach((topic, index) => { + const hotItem = this.createHotItem(topic, index); + this.elements.hotList.appendChild(hotItem); + }); + + this.showHotList(); + this.updateTimestamp(data.isCache); + } + + // 创建热搜项目元素 + createHotItem(topic, index) { + const item = document.createElement('div'); + item.className = 'hot-item'; + item.style.animationDelay = `${index * 0.1}s`; + + // 处理数据 + const rank = topic.rank || (index + 1); + const title = hotTopicsAPI.truncateText(topic.title, 80); + const desc = hotTopicsAPI.truncateText(topic.desc, 120); + const score = hotTopicsAPI.formatScore(topic.score, topic.score_desc); + const avatarUrl = hotTopicsAPI.processImageUrl(topic.avatar); + const topicUrl = hotTopicsAPI.processTopicUrl(topic.url); + const rankClass = hotTopicsAPI.getRankClass(rank); + + item.innerHTML = ` +
+
+ ${rank} +
+
+

${title}

+

${desc}

+
+
+ + ${score} +
+ ${avatarUrl ? `话题图片` : ''} +
+
+
+ `; + + // 添加点击事件 + item.addEventListener('click', () => { + this.openTopic(topicUrl, title); + }); + + // 添加长按事件(移动端) + let pressTimer; + item.addEventListener('touchstart', (e) => { + pressTimer = setTimeout(() => { + this.showTopicMenu(topic, e.touches[0].clientX, e.touches[0].clientY); + }, 500); + }); + + item.addEventListener('touchend', () => { + clearTimeout(pressTimer); + }); + + item.addEventListener('touchmove', () => { + clearTimeout(pressTimer); + }); + + return item; + } + + // 打开话题链接 + openTopic(url, title) { + if (url && url !== '#') { + // 在新窗口打开 + window.open(url, '_blank', 'noopener,noreferrer'); + } else { + this.showToast('链接暂不可用'); + } + } + + // 显示话题菜单(长按) + showTopicMenu(topic, x, y) { + const menu = document.createElement('div'); + menu.className = 'topic-menu'; + menu.style.cssText = ` + position: fixed; + left: ${x}px; + top: ${y}px; + background: white; + border-radius: 8px; + box-shadow: 0 4px 20px rgba(0,0,0,0.2); + padding: 8px 0; + z-index: 1000; + min-width: 120px; + `; + + const actions = [ + { text: '打开链接', action: () => this.openTopic(hotTopicsAPI.processTopicUrl(topic.url), topic.title) }, + { text: '复制标题', action: () => this.copyText(topic.title) }, + { text: '分享', action: () => this.shareContent(topic) } + ]; + + actions.forEach(action => { + const item = document.createElement('div'); + item.textContent = action.text; + item.style.cssText = ` + padding: 12px 16px; + cursor: pointer; + font-size: 14px; + color: #333; + border-bottom: 1px solid #f0f0f0; + `; + item.addEventListener('click', () => { + action.action(); + document.body.removeChild(menu); + }); + menu.appendChild(item); + }); + + document.body.appendChild(menu); + + // 点击其他地方关闭菜单 + setTimeout(() => { + document.addEventListener('click', function closeMenu() { + if (document.body.contains(menu)) { + document.body.removeChild(menu); + } + document.removeEventListener('click', closeMenu); + }); + }, 100); + } + + // 复制文本 + async copyText(text) { + try { + await navigator.clipboard.writeText(text); + this.showToast('已复制到剪贴板'); + } catch (error) { + console.error('复制失败:', error); + this.showToast('复制失败'); + } + } + + // 分享内容 + async shareContent(topic) { + const shareData = { + title: topic.title, + text: topic.desc, + url: hotTopicsAPI.processTopicUrl(topic.url) + }; + + try { + if (navigator.share) { + await navigator.share(shareData); + } else { + // 降级到复制链接 + await this.copyText(`${topic.title} - ${shareData.url}`); + } + } catch (error) { + console.error('分享失败:', error); + } + } + + // 显示提示消息 + showToast(message, duration = 2000) { + const toast = document.createElement('div'); + toast.textContent = message; + toast.style.cssText = ` + position: fixed; + bottom: 20px; + left: 50%; + transform: translateX(-50%); + background: rgba(0,0,0,0.8); + color: white; + padding: 12px 20px; + border-radius: 20px; + font-size: 14px; + z-index: 1000; + animation: fadeInUp 0.3s ease; + `; + + document.body.appendChild(toast); + + setTimeout(() => { + toast.style.animation = 'fadeOut 0.3s ease'; + setTimeout(() => { + if (document.body.contains(toast)) { + document.body.removeChild(toast); + } + }, 300); + }, duration); + } + + // 更新时间戳 + updateTimestamp(isCache = false) { + const now = new Date(); + const timeString = now.toLocaleString('zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit' + }); + + const cacheText = isCache ? ' (缓存数据)' : ''; + this.elements.updateTime.textContent = `最后更新:${timeString}${cacheText}`; + } + + // 刷新数据 + async refreshData() { + if (window.loadHotTopics) { + await window.loadHotTopics(); + } + } +} + +// 导出UI管理器实例 +const uiManager = new UIManager(); + +// 添加CSS动画 +const style = document.createElement('style'); +style.textContent = ` + @keyframes fadeOut { + from { opacity: 1; transform: translateX(-50%) translateY(0); } + to { opacity: 0; transform: translateX(-50%) translateY(10px); } + } +`; +document.head.appendChild(style); \ No newline at end of file diff --git a/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/返回接口.json b/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/返回接口.json new file mode 100644 index 00000000..7226ba5d --- /dev/null +++ b/InfoGenie-frontend/public/60sapi/热搜榜单/百度贴吧话题榜/返回接口.json @@ -0,0 +1,306 @@ +{ + "code": 200, + "message": "获取成功。数据来自官方/权威源头,以确保稳定与实时。开源地址 https://github.com/vikiboss/60s,反馈群 595941841", + "data": [ + { + "rank": 1, + "title": "MAGA喉舌被枪杀,川普为其降半旗", + "desc": "美国知名保守派活动人士、特朗普的政治盟友查理·柯克在大学演讲时遭枪击身亡,特朗普下令全美降半旗致哀。", + "abstract": "美国知名保守派活动人士、特朗普的政治盟友查理·柯克在大学演讲时遭枪击身亡,特朗普下令全美降半旗致哀。", + "score": 1594980, + "score_desc": "159.5w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=7fd9bdea3ad98d1076815f714702803a/a9d3fd1f4134970a614a3b39d3cad1c8a7865dee.jpg?tbpicau=2025-09-22-05_85ec313083b76eb31917067b6948c007", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344923&topic_name=MAGA%E5%96%89%E8%88%8C%E8%A2%AB%E6%9E%AA%E6%9D%80%2C%E5%B7%9D%E6%99%AE%E4%B8%BA%E5%85%B6%E9%99%8D%E5%8D%8A%E6%97%97" + }, + { + "rank": 2, + "title": "上膛!南理工打响整肃伪拳第一枪", + "desc": "终于有学校开了个好头,南京理工大学打响了武汉大学事件之后高校反对极端女权的第一枪。国防七子就是不一样,支持南理工!", + "abstract": "终于有学校开了个好头,南京理工大学打响了武汉大学事件之后高校反对极端女权的第一枪。国防七子就是不一样,支持南理工!", + "score": 1585575, + "score_desc": "158.56w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=45147a89e20f4bfb8c85cd14657240c4/8b13632762d0f703569980ca4efa513d2697c5f9.jpg?tbpicau=2025-09-22-05_8d101b01ab9f7032a8943a8ad9ad3591", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344934&topic_name=%E4%B8%8A%E8%86%9B%21%E5%8D%97%E7%90%86%E5%B7%A5%E6%89%93%E5%93%8D%E6%95%B4%E8%82%83%E4%BC%AA%E6%8B%B3%E7%AC%AC%E4%B8%80%E6%9E%AA" + }, + { + "rank": 3, + "title": "武大暗中篡改?杨某论文再次上架", + "desc": "又反转!武汉大学杨某媛“金牌”论文半夜又偷偷重新上架知网,不会是武大偷改好的版本吧,等热度一过就开始岁月史书?", + "abstract": "又反转!武汉大学杨某媛“金牌”论文半夜又偷偷重新上架知网,不会是武大偷改好的版本吧,等热度一过就开始岁月史书?", + "score": 1265376, + "score_desc": "126.54w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=e3f59fed7fdbb6fd250eb6666f19932c/8601a18b87d6277f2c00192e6e381f30e924fc92.jpg?tbpicau=2025-09-22-05_8c33e404e8488061ca9169977a762457", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344925&topic_name=%E6%AD%A6%E5%A4%A7%E6%9A%97%E4%B8%AD%E7%AF%A1%E6%94%B9%3F%E6%9D%A8%E6%9F%90%E8%AE%BA%E6%96%87%E5%86%8D%E6%AC%A1%E4%B8%8A%E6%9E%B6" + }, + { + "rank": 4, + "title": "兽王关键吼,XG大逆风翻盘石头人", + "desc": "落后1W6翻盘,Xxs刷新兽王关键吼,AME巨魔diff水晶。XG1比0石头人,拿下正赛首局,加油!", + "abstract": "落后1W6翻盘,Xxs刷新兽王关键吼,AME巨魔diff水晶。XG1比0石头人,拿下正赛首局,加油!", + "score": 893943, + "score_desc": "89.39w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=882897db1466d0167e4ccd68f116ec33/86d6277f9e2f070899cb3e16af24b899a801f2de.jpg?tbpicau=2025-09-22-05_625c74153fe7c84accea9ea76d88097b", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344941&topic_name=%E5%85%BD%E7%8E%8B%E5%85%B3%E9%94%AE%E5%90%BC%2CXG%E5%A4%A7%E9%80%86%E9%A3%8E%E7%BF%BB%E7%9B%98%E7%9F%B3%E5%A4%B4%E4%BA%BA" + }, + { + "rank": 5, + "title": "户圣开炮,安卓旗舰谁敢买?", + "desc": "户晨风再现逆天言论,苹果17发布,安卓中高端机遭遇灭顶之灾,两千五以上没人买,有能力的一定要给父母换iPhone!", + "abstract": "户晨风再现逆天言论,苹果17发布,安卓中高端机遭遇灭顶之灾,两千五以上没人买,有能力的一定要给父母换iPhone!", + "score": 766532, + "score_desc": "76.65w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=0eb028f7692eb938ec3829b2b35fbd01/c8177f3e6709c93d2a9825e1d93df8dcd10054b9.jpg?tbpicau=2025-09-22-05_a331d216b4e47c0049889f880fe693e3", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344926&topic_name=%E6%88%B7%E5%9C%A3%E5%BC%80%E7%82%AE%2C%E5%AE%89%E5%8D%93%E6%97%97%E8%88%B0%E8%B0%81%E6%95%A2%E4%B9%B0%3F" + }, + { + "rank": 6, + "title": "成都诬告偷拍败诉!小叶还能怎?", + "desc": "成都地铁诬告偷拍案二审维持原判,追风小叶维权失败,吧友锐评温和派的路走到头了。", + "abstract": "成都地铁诬告偷拍案二审维持原判,追风小叶维权失败,吧友锐评温和派的路走到头了。", + "score": 663175, + "score_desc": "66.32w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=9b41180f6bf5e0feee4dda413a5d0c9c/8694a4c27d1ed21b65aa39f3eb6eddc451da3f40.jpg?tbpicau=2025-09-22-05_db6b89b7846083172cde82c7146ebddc", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344942&topic_name=%E6%88%90%E9%83%BD%E8%AF%AC%E5%91%8A%E5%81%B7%E6%8B%8D%E8%B4%A5%E8%AF%89%21%E5%B0%8F%E5%8F%B6%E8%BF%98%E8%83%BD%E6%80%8E%3F" + }, + { + "rank": 7, + "title": "绝密飙至60w,盾奶开始泛滥", + "desc": "三角洲战备猛涨,玩家钱包 “躺平”!那些攥得紧紧、舍不得动的家底,这下不得不掏出来,打工一局倒贴钱,谁顶得住?", + "abstract": "三角洲战备猛涨,玩家钱包 “躺平”!那些攥得紧紧、舍不得动的家底,这下不得不掏出来,打工一局倒贴钱,谁顶得住?", + "score": 590856, + "score_desc": "59.09w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=61af83ea3ad98d1076815f714702803a/a9d3fd1f4134970a7f3c0539d3cad1c8a7865d5c.jpg?tbpicau=2025-09-22-05_82bc9423e1e1b97f3c071ce96e1cf7e4", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344936&topic_name=%E7%BB%9D%E5%AF%86%E9%A3%99%E8%87%B360w%2C%E7%9B%BE%E5%A5%B6%E5%BC%80%E5%A7%8B%E6%B3%9B%E6%BB%A5" + }, + { + "rank": 8, + "title": "邓紫棋被扒抢闺蜜男友博上位", + "desc": "邓紫棋被曝实锤撬闺蜜墙角,硬生生抢走正与闺蜜浓情蜜意的男友魏俊杰。事后为掩人耳目,还接连拉华晨宇、林宥嘉的绯闻来挡枪,一波操作引得舆论炸开了锅,粉丝纷纷 “跑路” 。", + "abstract": "邓紫棋被曝实锤撬闺蜜墙角,硬生生抢走正与闺蜜浓情蜜意的男友魏俊杰。事后为掩人耳目,还接连拉华晨宇、林宥嘉的绯闻来挡枪,一波操作引得舆论炸开了锅,粉丝纷纷 “跑路” 。", + "score": 506184, + "score_desc": "50.62w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=4d464c04094a20a4314b6f87f66fa016/30adcbef76094b36a2ff0ffbe5cc7cd98d109db2.jpg?tbpicau=2025-09-22-05_ed8c8f84187ef131dbb94421e614577b", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344937&topic_name=%E9%82%93%E7%B4%AB%E6%A3%8B%E8%A2%AB%E6%89%92%E6%8A%A2%E9%97%BA%E8%9C%9C%E7%94%B7%E5%8F%8B%E5%8D%9A%E4%B8%8A%E4%BD%8D" + }, + { + "rank": 9, + "title": "小红书被掘,薯民赛博戒网瘾", + "desc": "今天,网信办对小红书平台采取约谈、责令限期改正、警告、从严处理责任人等处置处罚措施。这下薯民们该何去何从?", + "abstract": "今天,网信办对小红书平台采取约谈、责令限期改正、警告、从严处理责任人等处置处罚措施。这下薯民们该何去何从?", + "score": 471548, + "score_desc": "47.15w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=51c0d93fc018367aaddc2c9d484eb3e0/bf096b63f6246b60eda2a662adf81a4c510fa27c.jpg?tbpicau=2025-09-22-05_61c56fced5303058de8e34d5f5c2f858", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344940&topic_name=%E5%B0%8F%E7%BA%A2%E4%B9%A6%E8%A2%AB%E6%8E%98%2C%E8%96%AF%E6%B0%91%E8%B5%9B%E5%8D%9A%E6%88%92%E7%BD%91%E7%98%BE" + }, + { + "rank": 10, + "title": "以军喊话轰全球:导弹是不长眼的", + "desc": "轰炸卡塔尔后以总理喊话全世界,称自己要效仿美国“9·11”事件后的行动,谁敢窝藏恐怖分子,以色列统统揍个遍!", + "abstract": "轰炸卡塔尔后以总理喊话全世界,称自己要效仿美国“9·11”事件后的行动,谁敢窝藏恐怖分子,以色列统统揍个遍!", + "score": 415002, + "score_desc": "41.5w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=6e77f03535f082022dc7c27f2dc6c3d9/562c11dfa9ec8a13a01b43f6b103918fa0ecc0a7.jpg?tbpicau=2025-09-22-05_492a74721d2be35b494d022729ab3727", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344938&topic_name=%E4%BB%A5%E5%86%9B%E5%96%8A%E8%AF%9D%E8%BD%B0%E5%85%A8%E7%90%83%3A%E5%AF%BC%E5%BC%B9%E6%98%AF%E4%B8%8D%E9%95%BF%E7%9C%BC%E7%9A%84" + }, + { + "rank": 11, + "title": "照抄还耗时?紫龙延迟补偿抠到爆", + "desc": "《第七史诗》紫龙又拉了,都25年了居然在白天维护服务器长达11个小时。延长这么久不说,打发玩家2000体力就想当无事发生,最起码补个光暗自选吧?", + "abstract": "《第七史诗》紫龙又拉了,都25年了居然在白天维护服务器长达11个小时。延长这么久不说,打发玩家2000体力就想当无事发生,最起码补个光暗自选吧?", + "score": 316800, + "score_desc": "31.68w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=4c344da7c60a19d8cb56d74555c7babf/7a899e510fb30f24c22cf8158e95d143ad4b0375.jpg?tbpicau=2025-09-22-05_ea3299a237a4be90f638d6f54ddfaee7", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344939&topic_name=%E7%85%A7%E6%8A%84%E8%BF%98%E8%80%97%E6%97%B6%3F%E7%B4%AB%E9%BE%99%E5%BB%B6%E8%BF%9F%E8%A1%A5%E5%81%BF%E6%8A%A0%E5%88%B0%E7%88%86" + }, + { + "rank": 12, + "title": "苹果是懂得维护韩男自尊心的", + "desc": "苹果市场部很懂韩国国情,还特意把新机海报上的敏感手势去掉了。", + "abstract": "苹果市场部很懂韩国国情,还特意把新机海报上的敏感手势去掉了。", + "score": 296609, + "score_desc": "29.66w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=16bc6dd6c4025aafd3672d8b9dd09350/10dfa9ec8a136327a57fe925d78fa0ec08fac712.jpg?tbpicau=2025-09-22-05_6d1258c530ad80062d801a0cdf3878c4", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344930&topic_name=%E8%8B%B9%E6%9E%9C%E6%98%AF%E6%87%82%E5%BE%97%E7%BB%B4%E6%8A%A4%E9%9F%A9%E7%94%B7%E8%87%AA%E5%B0%8A%E5%BF%83%E7%9A%84" + }, + { + "rank": 13, + "title": "米家胜!二游大逃杀,原神未滑档", + "desc": "国内畅销榜上,一众作品竞逐热度之际,《原神》稳居前列,凭独特玩法持续圈粉。网友直言:原神团队定是藏着 “神人”,决策方向始终正确,精准踩中玩家心巴。", + "abstract": "国内畅销榜上,一众作品竞逐热度之际,《原神》稳居前列,凭独特玩法持续圈粉。网友直言:原神团队定是藏着 “神人”,决策方向始终正确,精准踩中玩家心巴。", + "score": 210780, + "score_desc": "21.08w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=606b285c9cb44aed591beda4d521bf35/f7246b600c3387440d8b046a170fd9f9d72aa05e.jpg?tbpicau=2025-09-22-05_ac66e09b0535bcca38158c54002fa3c7", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344927&topic_name=%E7%B1%B3%E5%AE%B6%E8%83%9C%21%E4%BA%8C%E6%B8%B8%E5%A4%A7%E9%80%83%E6%9D%80%2C%E5%8E%9F%E7%A5%9E%E6%9C%AA%E6%BB%91%E6%A1%A3" + }, + { + "rank": 14, + "title": "秽土转生失败,动漫之家GG", + "desc": "动漫之家,终究还是停运了。起初反复刷新,还以为是网络出了问题,没想到它已经走了有一会儿了。这个无数漫迷的 “秘密基地”,如今却在激烈竞争与种种困境中再也回不来了。", + "abstract": "动漫之家,终究还是停运了。起初反复刷新,还以为是网络出了问题,没想到它已经走了有一会儿了。这个无数漫迷的 “秘密基地”,如今却在激烈竞争与种种困境中再也回不来了。", + "score": 207264, + "score_desc": "20.73w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=0db5d97a563853438c9ad461f52e884a/bd315c6034a85edfb52ed4350f540923dd547501.jpg?tbpicau=2025-09-22-05_9adff68227c9f67304fffc1a2731d758", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344932&topic_name=%E7%A7%BD%E5%9C%9F%E8%BD%AC%E7%94%9F%E5%A4%B1%E8%B4%A5%2C%E5%8A%A8%E6%BC%AB%E4%B9%8B%E5%AE%B6GG" + }, + { + "rank": 15, + "title": "张本两连败大飞,日男全军覆没", + "desc": "WTT澳门冠军赛男单1/16决赛,薛飞把张本智和打静音,横扫日乒一哥晋级,至此日本男队全部出局,这下真爆冷了。", + "abstract": "WTT澳门冠军赛男单1/16决赛,薛飞把张本智和打静音,横扫日乒一哥晋级,至此日本男队全部出局,这下真爆冷了。", + "score": 179152, + "score_desc": "17.92w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=1be7d7b39743ad4ba67b1580e43f629b/0bd162d9f2d3572cd30bb6cacc13632762d0c33f.jpg?tbpicau=2025-09-22-05_c5e594913af43484029ee1ccf719ee0a", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344933&topic_name=%E5%BC%A0%E6%9C%AC%E4%B8%A4%E8%BF%9E%E8%B4%A5%E5%A4%A7%E9%A3%9E%2C%E6%97%A5%E7%94%B7%E5%85%A8%E5%86%9B%E8%A6%86%E6%B2%A1" + }, + { + "rank": 16, + "title": "拳愿323:抽象的征西派内战", + "desc": "拳愿奥米迦323话大更:征西派的裂痕与王马的抉择,爱德华回生能力过于劣质,雷庵表现力太逆天,怕不是要成为决赛圈垫脚石?", + "abstract": "拳愿奥米迦323话大更:征西派的裂痕与王马的抉择,爱德华回生能力过于劣质,雷庵表现力太逆天,怕不是要成为决赛圈垫脚石?", + "score": 144915, + "score_desc": "14.49w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=65d67ff6b103918fd7846e8a37001ea3/b17eca8065380cd797d28afbe744ad34588281d3.jpg?tbpicau=2025-09-22-05_d45822c1109107fa7baacd2b01fefb61", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344924&topic_name=%E6%8B%B3%E6%84%BF323%3A%E6%8A%BD%E8%B1%A1%E7%9A%84%E5%BE%81%E8%A5%BF%E6%B4%BE%E5%86%85%E6%88%98" + }, + { + "rank": 17, + "title": "TES 3-1踩头WBG,灯皇薇恩送好局", + "desc": "LPL季后赛,TES对阵WBG。Light薇恩0输出葬送优势局,Kanavi潘森天降弑神,最终TES 3-1 WBG挺进胜决。", + "abstract": "LPL季后赛,TES对阵WBG。Light薇恩0输出葬送优势局,Kanavi潘森天降弑神,最终TES 3-1 WBG挺进胜决。", + "score": 108556, + "score_desc": "10.86w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=75e5576c66a446237e9ff622fe1f4a3a/caef76094b36acaf361abbea3ad98d1001e99c29.jpg?tbpicau=2025-09-22-05_dda77f28de2da58e81fcd3b6ff5aaacc", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344917&topic_name=TES%203-1%E8%B8%A9%E5%A4%B4WBG%2C%E7%81%AF%E7%9A%87%E8%96%87%E6%81%A9%E9%80%81%E5%A5%BD%E5%B1%80" + }, + { + "rank": 18, + "title": "师出有名,黄岩岛建立保护区", + "desc": "字少事大,国务院批复同意新建黄岩岛国家级自然保护区,隔壁菲猴还敢乱来吗?", + "abstract": "字少事大,国务院批复同意新建黄岩岛国家级自然保护区,隔壁菲猴还敢乱来吗?", + "score": 98280, + "score_desc": "9.83w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=31dba91375fa828bd176cea39b227900/43a7d933c895d14320aec93535f082025baf07cf.jpg?tbpicau=2025-09-22-05_b0badf07bc38a792ed54b85bb056f5aa", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344916&topic_name=%E5%B8%88%E5%87%BA%E6%9C%89%E5%90%8D%2C%E9%BB%84%E5%B2%A9%E5%B2%9B%E5%BB%BA%E7%AB%8B%E4%BF%9D%E6%8A%A4%E5%8C%BA" + }, + { + "rank": 19, + "title": "9月10日乐子限定", + "desc": "沪姐大战彩礼女,年轻人为了台苹果机不择手段,来看看昨天都有哪些乐子。", + "abstract": "沪姐大战彩礼女,年轻人为了台苹果机不择手段,来看看昨天都有哪些乐子。", + "score": 75660, + "score_desc": "7.57w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=f4c1e0dce951f3dec3e7ea24f2d3c82b/c9fcc3cec3fdfc03fb92cbae923f8794a4c22639.jpg?tbpicau=2025-09-22-05_04534fa7edbe9fa62b6c5170f11f6d42", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344922&topic_name=9%E6%9C%8810%E6%97%A5%E4%B9%90%E5%AD%90%E9%99%90%E5%AE%9A" + }, + { + "rank": 20, + "title": "每天一个宝藏吧——meme图吧", + "desc": "一个用梗图交流、靠表情包续命的赛博快乐老家,进来一个meme图小白,出去就是万人敬仰的meme图大师!", + "abstract": "一个用梗图交流、靠表情包续命的赛博快乐老家,进来一个meme图小白,出去就是万人敬仰的meme图大师!", + "score": 64691, + "score_desc": "6.47w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=366db542454f78f0805ec9b31f0c3261/908fa0ec08fa513deb1747c87b6d55fbb2fbd963.jpg?tbpicau=2025-09-22-05_0f79439d4fa718dccec3909f1093b1a0", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344928&topic_name=%E6%AF%8F%E5%A4%A9%E4%B8%80%E4%B8%AA%E5%AE%9D%E8%97%8F%E5%90%A7%E2%80%94%E2%80%94meme%E5%9B%BE%E5%90%A7" + }, + { + "rank": 21, + "title": "向鹏不敌德国选手,无缘十六强", + "desc": "在2025年世界乒乓球职业大联盟澳门冠军赛男子单打首轮比赛中,中国选手向鹏2比3不敌德国选手弗朗西斯卡,无缘16强。", + "abstract": "在2025年世界乒乓球职业大联盟澳门冠军赛男子单打首轮比赛中,中国选手向鹏2比3不敌德国选手弗朗西斯卡,无缘16强。", + "score": 51010, + "score_desc": "5.1w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=5110a6270c90f60304e5cf075f2f8b2f/91529822720e0cf30c5864ed4c46f21fbe09aa7d.jpg?tbpicau=2025-09-22-05_6494ac6b728dc643d62ecdfec9ffc10f", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344931&topic_name=%E5%90%91%E9%B9%8F%E4%B8%8D%E6%95%8C%E5%BE%B7%E5%9B%BD%E9%80%89%E6%89%8B%2C%E6%97%A0%E7%BC%98%E5%8D%81%E5%85%AD%E5%BC%BA" + }, + { + "rank": 22, + "title": "Faker虐爆许秀,T1险胜DK", + "desc": "绝境Faker再现!T1 3-2险胜DK,决胜局T1凭借关键团战逆转取胜。", + "abstract": "绝境Faker再现!T1 3-2险胜DK,决胜局T1凭借关键团战逆转取胜。", + "score": 47646, + "score_desc": "4.76w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=9d867145b0246b607b5be1348dc52278/55e736d12f2eb938b8df55e493628535e5dd6f71.jpg?tbpicau=2025-09-22-05_a1bfae75faab275c23b0f53a0a5b06ef", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344913&topic_name=Faker%E8%99%90%E7%88%86%E8%AE%B8%E7%A7%80%2CT1%E9%99%A9%E8%83%9CDK" + }, + { + "rank": 23, + "title": "张雪峰愿捐款打台独,媒体狂吠狠批", + "desc": "张雪峰说打台独自己捐五千万,大象新闻直接来了个大长篇,上来就给一个普通中国人的朴素爱国情怀扣上“鼓吹战争”的帽子,搞媒体的就这种素质?", + "abstract": "张雪峰说打台独自己捐五千万,大象新闻直接来了个大长篇,上来就给一个普通中国人的朴素爱国情怀扣上“鼓吹战争”的帽子,搞媒体的就这种素质?", + "score": 40064, + "score_desc": "4.01w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=2e4fc1ec3dcb0a468577d8790d5ece10/00e93901213fb80e595042c170d12f2eb9389426.jpg?tbpicau=2025-09-22-05_6e078e9f935aa244e26346ab37187ee2", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344910&topic_name=%E5%BC%A0%E9%9B%AA%E5%B3%B0%E6%84%BF%E6%8D%90%E6%AC%BE%E6%89%93%E5%8F%B0%E7%8B%AC%2C%E5%AA%92%E4%BD%93%E7%8B%82%E5%90%A0%E7%8B%A0%E6%89%B9" + }, + { + "rank": 24, + "title": "美军压境,委内瑞拉急盼歼10C", + "desc": "美军F-35A压境加勒比,委内瑞拉方寸大乱,紧急寻求采购歼10C。", + "abstract": "美军F-35A压境加勒比,委内瑞拉方寸大乱,紧急寻求采购歼10C。", + "score": 38052, + "score_desc": "3.81w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=90d8a718f73533faf5e3c06eceeec52b/0e2442a7d933c8955843b66d971373f0820200e2.jpg?tbpicau=2025-09-22-05_f8126e747fe76e25cfd9b3d3a75d1d54", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344921&topic_name=%E7%BE%8E%E5%86%9B%E5%8E%8B%E5%A2%83%2C%E5%A7%94%E5%86%85%E7%91%9E%E6%8B%89%E6%80%A5%E7%9B%BC%E6%AD%BC10C" + }, + { + "rank": 25, + "title": "真男人!海贼王龙哥射杀天龙人", + "desc": "海贼王1160话情报,龙开枪射击天龙人,救下红发双胞胎。昔日流汗王风评反转,龙哥成为海贼最有种的男人。", + "abstract": "海贼王1160话情报,龙开枪射击天龙人,救下红发双胞胎。昔日流汗王风评反转,龙哥成为海贼最有种的男人。", + "score": 26682, + "score_desc": "2.67w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=f8cb34fbe5cc7cd9fa7867995f3c190b/a71ea8d3fd1f4134c36e2a68631f95cad1c85e4e.jpg?tbpicau=2025-09-22-05_6853585b745b7349ad45ef38cf6df62f", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344920&topic_name=%E7%9C%9F%E7%94%B7%E4%BA%BA%21%E6%B5%B7%E8%B4%BC%E7%8E%8B%E9%BE%99%E5%93%A5%E5%B0%84%E6%9D%80%E5%A4%A9%E9%BE%99%E4%BA%BA" + }, + { + "rank": 26, + "title": "三角洲免费送点券,玩家争当洲孝子", + "desc": "三角洲行动周年庆福利拉满,免费送3900三角券。玩家火速倒戈,暂停讨伐制作组,怒赞策划太良心。", + "abstract": "三角洲行动周年庆福利拉满,免费送3900三角券。玩家火速倒戈,暂停讨伐制作组,怒赞策划太良心。", + "score": 25255, + "score_desc": "2.53w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=c4d99672d2eef01f4d414b8586c3a111/9345d688d43f8794d4946738941b0ef41bd53ab8.jpg?tbpicau=2025-09-22-05_a2046d59aca4681d2f9495edce4c3b25", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344919&topic_name=%E4%B8%89%E8%A7%92%E6%B4%B2%E5%85%8D%E8%B4%B9%E9%80%81%E7%82%B9%E5%88%B8%2C%E7%8E%A9%E5%AE%B6%E4%BA%89%E5%BD%93%E6%B4%B2%E5%AD%9D%E5%AD%90" + }, + { + "rank": 27, + "title": "以空袭卡塔尔,暗杀哈马斯未得逞", + "desc": "以色列对身处卡塔尔首都多哈的哈马斯领导层发动所谓精准打击,并证实哈马斯5名成员死于以军空袭,但以方暗杀哈马斯高层的图谋未能得逞。", + "abstract": "以色列对身处卡塔尔首都多哈的哈马斯领导层发动所谓精准打击,并证实哈马斯5名成员死于以军空袭,但以方暗杀哈马斯高层的图谋未能得逞。", + "score": 20900, + "score_desc": "2.09w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=5eb82d27673fb80e0c84329750ec171a/314e251f95cad1c8f8d7dd31393e6709c93d51b3.jpg?tbpicau=2025-09-22-05_cf088fe88563cb500e0581d892800736", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344898&topic_name=%E4%BB%A5%E7%A9%BA%E8%A2%AD%E5%8D%A1%E5%A1%94%E5%B0%94%2C%E6%9A%97%E6%9D%80%E5%93%88%E9%A9%AC%E6%96%AF%E6%9C%AA%E5%BE%97%E9%80%9E" + }, + { + "rank": 28, + "title": "局座出山,战忽局要开工了?", + "desc": "神隐五年之后,被网友戏称“战略忽悠局局长”的军事评论家张召忠重出江湖参加讲座。国际局势风云变幻,战忽局还有市场吗?", + "abstract": "神隐五年之后,被网友戏称“战略忽悠局局长”的军事评论家张召忠重出江湖参加讲座。国际局势风云变幻,战忽局还有市场吗?", + "score": 20166, + "score_desc": "2.02w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=c4150e6a170fd9f9a04206294310ec1e/d4628535e5dde711bf0262e0e1efce1b9c1661d7.jpg?tbpicau=2025-09-22-05_f7db127146ec115d51ff7ede6261253e", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344903&topic_name=%E5%B1%80%E5%BA%A7%E5%87%BA%E5%B1%B1%2C%E6%88%98%E5%BF%BD%E5%B1%80%E8%A6%81%E5%BC%80%E5%B7%A5%E4%BA%86%3F" + }, + { + "rank": 29, + "title": "丝之歌光速滑跪,更新补丁降难度", + "desc": "《空洞骑士:丝之歌》游戏难度逆天差评不断,制作组官宣更新补丁,前期BOSS难度降低、奖励增加。", + "abstract": "《空洞骑士:丝之歌》游戏难度逆天差评不断,制作组官宣更新补丁,前期BOSS难度降低、奖励增加。", + "score": 14526, + "score_desc": "1.45w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=420c2d34f51bb0518f71e0685047e280/7acb0a46f21fbe098018e2022d600c338744ad66.jpg?tbpicau=2025-09-22-05_95664e9657ba0ab59a428fd9a3db30b7", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344899&topic_name=%E4%B8%9D%E4%B9%8B%E6%AD%8C%E5%85%89%E9%80%9F%E6%BB%91%E8%B7%AA%2C%E6%9B%B4%E6%96%B0%E8%A1%A5%E4%B8%81%E9%99%8D%E9%9A%BE%E5%BA%A6" + }, + { + "rank": 30, + "title": "倭殖入脑,武大再现逆天论文", + "desc": "近日,武汉大学又被挖出一篇关于”传统武士道精神下的女性形象“的逆天论文,武汉大学持续发力,吧友吐槽“武大的文科真是奇迹般的存在 ”", + "abstract": "近日,武汉大学又被挖出一篇关于”传统武士道精神下的女性形象“的逆天论文,武汉大学持续发力,吧友吐槽“武大的文科真是奇迹般的存在 ”", + "score": 13717, + "score_desc": "1.37w", + "avatar": "https://tiebapic.baidu.com/forum/whfpf%3D84%2C88%2C40%3Bq%3D90/sign=71b4b4adc1d6277fe94761784e052704/d8f9d72a6059252d229f3d12729b033b5bb5b918.jpg?tbpicau=2025-09-22-05_71986e04f0934ae41569ea8d11844675", + "url": "https://tieba.baidu.com/hottopic/browse/hottopic?topic_id=28344905&topic_name=%E5%80%AD%E6%AE%96%E5%85%A5%E8%84%91%2C%E6%AD%A6%E5%A4%A7%E5%86%8D%E7%8E%B0%E9%80%86%E5%A4%A9%E8%AE%BA%E6%96%87" + } + ] +} \ No newline at end of file diff --git a/frontend/public/60sapi/热搜榜单/知乎热门话题/css/background.css b/InfoGenie-frontend/public/60sapi/热搜榜单/知乎热门话题/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/知乎热门话题/css/background.css rename to InfoGenie-frontend/public/60sapi/热搜榜单/知乎热门话题/css/background.css diff --git a/frontend/public/60sapi/热搜榜单/知乎热门话题/css/style.css b/InfoGenie-frontend/public/60sapi/热搜榜单/知乎热门话题/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/知乎热门话题/css/style.css rename to InfoGenie-frontend/public/60sapi/热搜榜单/知乎热门话题/css/style.css diff --git a/frontend/public/60sapi/热搜榜单/知乎热门话题/img/zhihu-logo.svg b/InfoGenie-frontend/public/60sapi/热搜榜单/知乎热门话题/img/zhihu-logo.svg old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/知乎热门话题/img/zhihu-logo.svg rename to InfoGenie-frontend/public/60sapi/热搜榜单/知乎热门话题/img/zhihu-logo.svg diff --git a/frontend/public/60sapi/热搜榜单/知乎热门话题/index.html b/InfoGenie-frontend/public/60sapi/热搜榜单/知乎热门话题/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/知乎热门话题/index.html rename to InfoGenie-frontend/public/60sapi/热搜榜单/知乎热门话题/index.html diff --git a/frontend/public/60sapi/热搜榜单/知乎热门话题/js/main.js b/InfoGenie-frontend/public/60sapi/热搜榜单/知乎热门话题/js/main.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/知乎热门话题/js/main.js rename to InfoGenie-frontend/public/60sapi/热搜榜单/知乎热门话题/js/main.js diff --git a/frontend/public/60sapi/热搜榜单/知乎热门话题/接口集合.json b/InfoGenie-frontend/public/60sapi/热搜榜单/知乎热门话题/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/知乎热门话题/接口集合.json rename to InfoGenie-frontend/public/60sapi/热搜榜单/知乎热门话题/接口集合.json diff --git a/frontend/public/60sapi/热搜榜单/知乎热门话题/返回接口.json b/InfoGenie-frontend/public/60sapi/热搜榜单/知乎热门话题/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/知乎热门话题/返回接口.json rename to InfoGenie-frontend/public/60sapi/热搜榜单/知乎热门话题/返回接口.json diff --git a/frontend/public/60sapi/热搜榜单/网易云榜单/css/background.css b/InfoGenie-frontend/public/60sapi/热搜榜单/网易云榜单/css/background.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/网易云榜单/css/background.css rename to InfoGenie-frontend/public/60sapi/热搜榜单/网易云榜单/css/background.css diff --git a/frontend/public/60sapi/热搜榜单/网易云榜单/css/responsive.css b/InfoGenie-frontend/public/60sapi/热搜榜单/网易云榜单/css/responsive.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/网易云榜单/css/responsive.css rename to InfoGenie-frontend/public/60sapi/热搜榜单/网易云榜单/css/responsive.css diff --git a/frontend/public/60sapi/热搜榜单/网易云榜单/css/style.css b/InfoGenie-frontend/public/60sapi/热搜榜单/网易云榜单/css/style.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/网易云榜单/css/style.css rename to InfoGenie-frontend/public/60sapi/热搜榜单/网易云榜单/css/style.css diff --git a/frontend/public/60sapi/热搜榜单/网易云榜单/index.html b/InfoGenie-frontend/public/60sapi/热搜榜单/网易云榜单/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/网易云榜单/index.html rename to InfoGenie-frontend/public/60sapi/热搜榜单/网易云榜单/index.html diff --git a/frontend/public/60sapi/热搜榜单/网易云榜单/js/app.js b/InfoGenie-frontend/public/60sapi/热搜榜单/网易云榜单/js/app.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/网易云榜单/js/app.js rename to InfoGenie-frontend/public/60sapi/热搜榜单/网易云榜单/js/app.js diff --git a/frontend/public/60sapi/热搜榜单/网易云榜单/接口集合.json b/InfoGenie-frontend/public/60sapi/热搜榜单/网易云榜单/接口集合.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/网易云榜单/接口集合.json rename to InfoGenie-frontend/public/60sapi/热搜榜单/网易云榜单/接口集合.json diff --git a/frontend/public/60sapi/热搜榜单/网易云榜单/返回接口.json b/InfoGenie-frontend/public/60sapi/热搜榜单/网易云榜单/返回接口.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/热搜榜单/网易云榜单/返回接口.json rename to InfoGenie-frontend/public/60sapi/热搜榜单/网易云榜单/返回接口.json diff --git a/frontend/public/60sapi/生成要求模板.txt b/InfoGenie-frontend/public/60sapi/生成要求模板.txt old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/60sapi/生成要求模板.txt rename to InfoGenie-frontend/public/60sapi/生成要求模板.txt diff --git a/frontend/public/_redirects b/InfoGenie-frontend/public/_redirects old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/_redirects rename to InfoGenie-frontend/public/_redirects diff --git a/InfoGenie-frontend/public/aimodelapp/AI写诗小助手/index.html b/InfoGenie-frontend/public/aimodelapp/AI写诗小助手/index.html new file mode 100644 index 00000000..fe5fb5da --- /dev/null +++ b/InfoGenie-frontend/public/aimodelapp/AI写诗小助手/index.html @@ -0,0 +1,246 @@ + + + + + + AI古诗生成器 + + + +
+
+

AI古诗生成器

+

让人工智能为您创作优美的中国古诗

+
+ + + +
+ + +
+ + + +
+

生成的古诗

+
正在创作中,请稍候...
+
点击"生成古诗"按钮,AI将为您创作优美的古诗
+
+
+ + + + + \ No newline at end of file diff --git a/InfoGenie-frontend/public/aimodelapp/AI写诗小助手/script.js b/InfoGenie-frontend/public/aimodelapp/AI写诗小助手/script.js new file mode 100644 index 00000000..090bc8bf --- /dev/null +++ b/InfoGenie-frontend/public/aimodelapp/AI写诗小助手/script.js @@ -0,0 +1,109 @@ +// 从配置文件导入设置 +// 配置在 env.js 文件中定义 + +// DOM 元素 +const generateBtn = document.getElementById('generateBtn'); +const loading = document.getElementById('loading'); +const poemOutput = document.getElementById('poemOutput'); +const themeInput = document.getElementById('theme'); + +// 调用后端API +async function callBackendAPI(theme) { + try { + const response = await fetch('http://127.0.0.1:5002/api/aimodelapp/poetry', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + theme: theme + }) + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.error || `API请求失败: ${response.status} ${response.statusText}`); + } + + const data = await response.json(); + if (data.success) { + return data.poem; + } else { + throw new Error(data.error || 'API响应格式异常'); + } + } catch (error) { + console.error('API调用错误:', error); + throw error; + } +} + +// 显示错误信息 +function showErrorMessage(message) { + // 清除之前的错误信息 + const existingError = document.querySelector('.error'); + if (existingError) { + existingError.remove(); + } + + const errorDiv = document.createElement('div'); + errorDiv.className = 'error'; + errorDiv.textContent = `生成失败:${message}。请检查网络连接。`; + poemOutput.parentNode.appendChild(errorDiv); +} + +// 显示加载状态 +function showLoading(show) { + loading.style.display = show ? 'block' : 'none'; + generateBtn.disabled = show; + generateBtn.textContent = show ? '创作中...' : '生成古诗'; +} + +// 生成古诗 +async function generatePoem() { + const theme = themeInput.value.trim(); + + if (!theme) { + alert('请输入作诗主题'); + return; + } + + showLoading(true); + poemOutput.textContent = ''; + + // 清除之前的错误信息 + const existingError = document.querySelector('.error'); + if (existingError) { + existingError.remove(); + } + + try { + const poem = await callBackendAPI(theme); + poemOutput.textContent = poem.trim(); + } catch (error) { + console.error('生成古诗失败:', error); + showErrorMessage(error.message); + poemOutput.textContent = '生成失败,请重试'; + } finally { + showLoading(false); + } +} + +// 事件监听器 +generateBtn.addEventListener('click', generatePoem); + +// 回车键生成 +themeInput.addEventListener('keypress', (e) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + generatePoem(); + } +}); + +// 页面加载完成后的初始化 +document.addEventListener('DOMContentLoaded', () => { + // 设置默认占位符 + poemOutput.textContent = '点击"生成古诗"按钮,AI将为您创作优美的古诗'; +}); + +// 导出函数供HTML调用 +window.generatePoem = generatePoem; \ No newline at end of file diff --git a/frontend/public/aimodelapp/AI变量命名助手/index.html b/InfoGenie-frontend/public/aimodelapp/AI变量命名助手/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/aimodelapp/AI变量命名助手/index.html rename to InfoGenie-frontend/public/aimodelapp/AI变量命名助手/index.html diff --git a/frontend/public/aimodelapp/AI变量命名助手/script.js b/InfoGenie-frontend/public/aimodelapp/AI变量命名助手/script.js old mode 100755 new mode 100644 similarity index 89% rename from frontend/public/aimodelapp/AI变量命名助手/script.js rename to InfoGenie-frontend/public/aimodelapp/AI变量命名助手/script.js index 0fc146b2..2dff09f9 --- a/frontend/public/aimodelapp/AI变量命名助手/script.js +++ b/InfoGenie-frontend/public/aimodelapp/AI变量命名助手/script.js @@ -37,34 +37,30 @@ const namingConventions = { -// 调用GitHub Models API -async function callGitHubModelsAPI(prompt) { +// 调用后端API +async function callBackendAPI(description) { try { - const response = await fetch(CONFIG.API_URL, { + const response = await fetch('http://127.0.0.1:5002/api/aimodelapp/variable-naming', { method: 'POST', headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${CONFIG.GITHUB_TOKEN}` + 'Content-Type': 'application/json' }, body: JSON.stringify({ - messages: [ - { - role: 'user', - content: prompt - } - ], - model: CONFIG.MODEL_NAME, - temperature: 0.7, - max_tokens: 1000 + description: description }) }); if (!response.ok) { - throw new Error(`API请求失败: ${response.status} ${response.statusText}`); + const errorData = await response.json(); + throw new Error(errorData.error || `API请求失败: ${response.status} ${response.statusText}`); } const data = await response.json(); - return data.choices[0].message.content; + if (data.success) { + return data.suggestions; + } else { + throw new Error(data.error || 'API响应格式异常'); + } } catch (error) { console.error('API调用错误:', error); throw error; @@ -216,10 +212,7 @@ async function generateSuggestions() { suggestionsContainer.innerHTML = ''; try { - const prompt = CONFIG.createNamingPrompt(description); - const response = await callGitHubModelsAPI(prompt); - const suggestions = parseAIResponse(response); - + const suggestions = await callBackendAPI(description); displaySuggestions(suggestions); } catch (error) { console.error('生成建议失败:', error); diff --git a/frontend/public/aimodelapp/AI变量命名助手/styles.css b/InfoGenie-frontend/public/aimodelapp/AI变量命名助手/styles.css old mode 100755 new mode 100644 similarity index 51% rename from frontend/public/aimodelapp/AI变量命名助手/styles.css rename to InfoGenie-frontend/public/aimodelapp/AI变量命名助手/styles.css index 3174cc43..c6d4bd14 --- a/frontend/public/aimodelapp/AI变量命名助手/styles.css +++ b/InfoGenie-frontend/public/aimodelapp/AI变量命名助手/styles.css @@ -5,80 +5,85 @@ box-sizing: border-box; } -/* 主体样式 */ +/* 主体样式 - iOS风格 */ body { - font-family: 'Microsoft YaHei', '微软雅黑', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Helvetica Neue', Arial, sans-serif; + background: linear-gradient(135deg, #87CEEB 0%, #98FB98 100%); min-height: 100vh; padding: 20px; - color: #333; - line-height: 1.6; + color: #1D1D1F; + line-height: 1.47; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } -/* 容器样式 */ +/* 容器样式 - iOS毛玻璃效果 */ .container { max-width: 700px; margin: 0 auto; - background: rgba(255, 255, 255, 0.95); - border-radius: 20px; - padding: 30px; - box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); - backdrop-filter: blur(10px); + background: rgba(255, 255, 255, 0.85); + border-radius: 24px; + padding: 32px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.08); + backdrop-filter: blur(20px) saturate(180%); + border: 1px solid rgba(255, 255, 255, 0.2); } -/* 头部样式 */ +/* 头部样式 - iOS风格 */ .header { text-align: center; - margin-bottom: 30px; + margin-bottom: 32px; } .title { - font-size: 2.5rem; - color: #4a5568; - margin-bottom: 10px; - font-weight: 300; - letter-spacing: 2px; + font-size: 2.25rem; + color: #1D1D1F; + margin-bottom: 8px; + font-weight: 600; + letter-spacing: -0.02em; } .subtitle { - color: #718096; - font-size: 1rem; - margin-bottom: 20px; + color: #86868B; + font-size: 1.0625rem; + margin-bottom: 24px; + font-weight: 400; } -/* 表单样式 */ +/* 表单样式 - iOS风格 */ .form-section { - margin-bottom: 30px; + margin-bottom: 32px; } .form-group { - margin-bottom: 25px; + margin-bottom: 24px; } .form-label { display: block; margin-bottom: 8px; - font-weight: 500; - color: #4a5568; + font-weight: 600; + color: #1D1D1F; font-size: 1rem; } .form-input { width: 100%; - padding: 15px; - border: 2px solid #e2e8f0; + padding: 16px; + border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 12px; font-size: 1rem; - transition: all 0.3s ease; - background: #f7fafc; + transition: all 0.2s ease; + background: rgba(255, 255, 255, 0.8); font-family: inherit; + backdrop-filter: blur(10px); } .form-input:focus { outline: none; - border-color: #667eea; - background: #fff; - box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); + border-color: #007AFF; + background: rgba(255, 255, 255, 0.95); + box-shadow: 0 0 0 4px rgba(0, 122, 255, 0.1); } .textarea { @@ -96,104 +101,113 @@ body { padding-right: 40px; } -/* 按钮样式 */ +/* 按钮样式 - iOS风格 */ .btn { width: 100%; - padding: 15px; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + padding: 16px; + background: #007AFF; color: white; border: none; border-radius: 12px; - font-size: 1.1rem; - font-weight: 500; + font-size: 1.0625rem; + font-weight: 600; cursor: pointer; - transition: all 0.3s ease; - margin-bottom: 25px; + transition: all 0.2s ease; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(0, 122, 255, 0.25); } .btn:hover { - transform: translateY(-2px); - box-shadow: 0 10px 25px rgba(102, 126, 234, 0.3); + background: #0056CC; + transform: translateY(-1px); + box-shadow: 0 4px 16px rgba(0, 122, 255, 0.35); } .btn:active { transform: translateY(0); + background: #004499; } .btn:disabled { - opacity: 0.6; + opacity: 0.5; cursor: not-allowed; transform: none; + background: #86868B; } -/* 结果区域样式 */ +/* 结果区域样式 - iOS风格 */ .result-section { - margin-top: 30px; + margin-top: 32px; } .result-title { - font-size: 1.3rem; - color: #4a5568; - margin-bottom: 15px; + font-size: 1.25rem; + color: #1D1D1F; + margin-bottom: 16px; text-align: center; - font-weight: 500; + font-weight: 600; } .loading { display: none; text-align: center; - color: #667eea; - font-style: italic; - padding: 20px; + color: #007AFF; + font-style: normal; + padding: 24px; + font-weight: 500; } .suggestions-container { - background: #f7fafc; - border: 2px solid #e2e8f0; - border-radius: 12px; - padding: 20px; + background: rgba(255, 255, 255, 0.6); + border: 1px solid rgba(0, 0, 0, 0.08); + border-radius: 16px; + padding: 24px; min-height: 150px; + backdrop-filter: blur(10px); } .placeholder { text-align: center; - color: #a0aec0; - font-style: italic; + color: #86868B; + font-style: normal; padding: 40px 20px; + font-weight: 400; } -/* 分组标题样式 */ +/* 分组标题样式 - iOS风格 */ .convention-group-title { - font-size: 1.1rem; + font-size: 1.0625rem; font-weight: 600; - color: #4a5568; - margin: 20px 0 10px 0; - padding: 8px 12px; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; - border-radius: 8px; + margin: 20px 0 12px 0; + padding: 12px 16px; + background: #007AFF; + border-radius: 12px; text-align: center; + box-shadow: 0 2px 8px rgba(0, 122, 255, 0.25); } .convention-group-title:first-child { margin-top: 0; } -/* 建议项样式 */ +/* 建议项样式 - iOS风格 */ .suggestion-item { - background: #fff; - border: 1px solid #e2e8f0; - border-radius: 8px; - padding: 15px; - margin-bottom: 10px; + background: rgba(255, 255, 255, 0.9); + border: 1px solid rgba(0, 0, 0, 0.06); + border-radius: 12px; + padding: 16px; + margin-bottom: 12px; transition: all 0.2s ease; cursor: pointer; position: relative; + backdrop-filter: blur(10px); } .suggestion-item:hover { - border-color: #667eea; - box-shadow: 0 2px 8px rgba(102, 126, 234, 0.1); + border-color: rgba(0, 122, 255, 0.3); + box-shadow: 0 4px 16px rgba(0, 122, 255, 0.1); + background: rgba(255, 255, 255, 0.95); } .suggestion-item:last-child { @@ -201,32 +215,34 @@ body { } .variable-name { - font-family: 'Consolas', 'Monaco', 'Courier New', monospace; - font-size: 1.1rem; + font-family: 'SF Mono', 'Monaco', 'Consolas', 'Courier New', monospace; + font-size: 1.0625rem; font-weight: 600; - color: #2d3748; - margin-bottom: 5px; + color: #1D1D1F; + margin-bottom: 6px; } .variable-description { - font-size: 0.9rem; - color: #718096; - line-height: 1.4; + font-size: 0.9375rem; + color: #86868B; + line-height: 1.47; } .copy-btn { position: absolute; - top: 10px; - right: 10px; - background: #667eea; + top: 12px; + right: 12px; + background: #007AFF; color: white; border: none; - border-radius: 6px; - padding: 5px 10px; - font-size: 0.8rem; + border-radius: 8px; + padding: 6px 12px; + font-size: 0.8125rem; + font-weight: 600; cursor: pointer; opacity: 0; - transition: opacity 0.2s ease; + transition: all 0.2s ease; + box-shadow: 0 2px 4px rgba(0, 122, 255, 0.25); } .suggestion-item:hover .copy-btn { @@ -234,33 +250,38 @@ body { } .copy-btn:hover { - background: #5a67d8; + background: #0056CC; + transform: translateY(-1px); } -/* 错误样式 */ +/* 错误样式 - iOS风格 */ .error { - color: #e53e3e; - background: #fed7d7; - border: 1px solid #feb2b2; - padding: 15px; - border-radius: 8px; - margin-top: 15px; + color: #FF3B30; + background: rgba(255, 59, 48, 0.1); + border: 1px solid rgba(255, 59, 48, 0.2); + padding: 16px; + border-radius: 12px; + margin-top: 16px; + font-weight: 500; + backdrop-filter: blur(10px); } -/* 成功提示 */ +/* 成功提示 - iOS风格 */ .success-toast { position: fixed; top: 20px; right: 20px; - background: #48bb78; + background: #34C759; color: white; padding: 12px 20px; - border-radius: 8px; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + border-radius: 12px; + box-shadow: 0 8px 24px rgba(52, 199, 89, 0.3); z-index: 1000; opacity: 0; transform: translateX(100%); transition: all 0.3s ease; + font-weight: 600; + backdrop-filter: blur(20px); } .success-toast.show { diff --git a/frontend/public/aimodelapp/AI姓名评测/index.html b/InfoGenie-frontend/public/aimodelapp/AI姓名评测/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/aimodelapp/AI姓名评测/index.html rename to InfoGenie-frontend/public/aimodelapp/AI姓名评测/index.html diff --git a/frontend/public/aimodelapp/AI姓名评测/script.js b/InfoGenie-frontend/public/aimodelapp/AI姓名评测/script.js old mode 100755 new mode 100644 similarity index 91% rename from frontend/public/aimodelapp/AI姓名评测/script.js rename to InfoGenie-frontend/public/aimodelapp/AI姓名评测/script.js index 4c21830a..d38ecbb5 --- a/frontend/public/aimodelapp/AI姓名评测/script.js +++ b/InfoGenie-frontend/public/aimodelapp/AI姓名评测/script.js @@ -188,22 +188,14 @@ async function analyzeName() { } const requestBody = { - model: CONFIG.model, - messages: [{ - role: "user", - content: CONFIG.createNameAnalysisPrompt(name) - }], - temperature: 0.7, - max_tokens: 1000 + name: name }; try { - const response = await fetch(CONFIG.endpoint, { + // 调用后端API + const response = await fetch('http://127.0.0.1:5002/api/aimodelapp/name-analysis', { method: 'POST', headers: { - 'Accept': 'application/vnd.github+json', - 'Authorization': `Bearer ${CONFIG.GITHUB_TOKEN}`, - 'X-GitHub-Api-Version': '2022-11-28', 'Content-Type': 'application/json' }, body: JSON.stringify(requestBody) @@ -215,16 +207,17 @@ async function analyzeName() { } if (!response.ok) { - throw new Error(`请求失败: ${response.status} ${response.statusText}`); + const errorData = await response.json(); + throw new Error(errorData.error || `请求失败: ${response.status} ${response.statusText}`); } const data = await response.json(); - if (data?.choices?.[0]?.message?.content) { - const analysisResult = parseAnalysisResult(data.choices[0].message.content.trim()); + if (data.success && data.analysis) { + const analysisResult = parseAnalysisResult(data.analysis.trim()); updateResults(analysisResult); } else { - throw new Error('AI响应格式异常'); + throw new Error(data.error || 'AI响应格式异常'); } } catch (error) { console.error('分析姓名时出错:', error); diff --git a/InfoGenie-frontend/public/aimodelapp/AI姓名评测/styles.css b/InfoGenie-frontend/public/aimodelapp/AI姓名评测/styles.css new file mode 100644 index 00000000..a833bca8 --- /dev/null +++ b/InfoGenie-frontend/public/aimodelapp/AI姓名评测/styles.css @@ -0,0 +1,265 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Helvetica Neue', Arial, sans-serif; + background: linear-gradient(135deg, #87CEEB 0%, #98FB98 100%); + min-height: 100vh; + padding: 20px; + color: #1D1D1F; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.container { + max-width: 700px; + margin: 0 auto; + background: rgba(255, 255, 255, 0.85); + border-radius: 24px; + padding: 32px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.08); + backdrop-filter: blur(20px) saturate(180%); + border: 1px solid rgba(255, 255, 255, 0.2); +} + +.header { + text-align: center; + margin-bottom: 32px; +} + +.title { + font-size: 2.25rem; + color: #1D1D1F; + margin-bottom: 8px; + font-weight: 600; + letter-spacing: -0.02em; +} + +.subtitle { + color: #86868B; + font-size: 1.0625rem; + margin-bottom: 24px; + font-weight: 400; +} + +.form-group { + margin-bottom: 24px; +} + +.form-label { + display: block; + margin-bottom: 8px; + font-weight: 600; + color: #1D1D1F; + font-size: 1rem; +} + +.form-input { + width: 100%; + padding: 16px; + border: 1px solid rgba(0, 0, 0, 0.1); + border-radius: 12px; + font-size: 1rem; + transition: all 0.2s ease; + background: rgba(255, 255, 255, 0.8); + text-align: center; + backdrop-filter: blur(10px); +} + +.form-input:focus { + outline: none; + border-color: #007AFF; + background: rgba(255, 255, 255, 0.95); + box-shadow: 0 0 0 4px rgba(0, 122, 255, 0.1); +} + +.btn { + width: 100%; + padding: 16px; + background: #007AFF; + color: white; + border: none; + border-radius: 12px; + font-size: 1.0625rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(0, 122, 255, 0.25); +} + +.btn:hover { + background: #0056CC; + transform: translateY(-1px); + box-shadow: 0 4px 16px rgba(0, 122, 255, 0.35); +} + +.btn:active { + transform: translateY(0); + background: #004499; +} + +.btn:disabled { + opacity: 0.5; + cursor: not-allowed; + transform: none; + background: #86868B; +} + +.result-section { + margin-top: 32px; +} + +.result-title { + font-size: 1.25rem; + color: #1D1D1F; + margin-bottom: 20px; + text-align: center; + font-weight: 600; +} + +.loading { + display: none; + text-align: center; + color: #007AFF; + font-style: normal; + margin-bottom: 20px; + font-weight: 500; +} + +.result-container { + display: grid; + gap: 16px; + grid-template-columns: 1fr; +} + +.result-card { + background: rgba(255, 255, 255, 0.6); + border: 1px solid rgba(0, 0, 0, 0.08); + border-radius: 16px; + padding: 24px; + transition: all 0.2s ease; + backdrop-filter: blur(10px); +} + +.result-card:hover { + border-color: rgba(0, 122, 255, 0.3); + box-shadow: 0 4px 16px rgba(0, 122, 255, 0.1); + background: rgba(255, 255, 255, 0.8); +} + +.card-title { + font-size: 1.0625rem; + color: #1D1D1F; + margin-bottom: 16px; + text-align: center; + font-weight: 600; +} + +.score-display { + font-size: 2.25rem; + font-weight: 700; + text-align: center; + margin-bottom: 12px; + background: linear-gradient(135deg, #007AFF 0%, #5856D6 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.score-desc { + text-align: center; + color: #86868B; + font-size: 0.9375rem; + line-height: 1.47; + font-weight: 400; +} + +.meaning-content { + color: #1D1D1F; + line-height: 1.6; + font-size: 1rem; + text-align: left; + white-space: pre-wrap; + font-weight: 400; +} + +.error { + color: #FF3B30; + background: rgba(255, 59, 48, 0.1); + border: 1px solid rgba(255, 59, 48, 0.2); + padding: 16px; + border-radius: 12px; + margin-top: 16px; + font-weight: 500; + backdrop-filter: blur(10px); +} + +/* 平板和桌面端优化 */ +@media (min-width: 768px) { + .result-container { + grid-template-columns: 1fr 1fr; + } + + .result-card:last-child { + grid-column: 1 / -1; + } +} + +/* 手机端优化 */ +@media (max-width: 768px) { + body { + padding: 10px; + } + + .container { + padding: 20px; + margin: 10px; + } + + .title { + font-size: 2rem; + } + + .form-input { + padding: 12px; + } + + .btn { + padding: 12px; + } + + .result-card { + padding: 15px; + } + + .score-display { + font-size: 2rem; + } +} + +@media (max-width: 480px) { + .title { + font-size: 1.8rem; + letter-spacing: 1px; + } + + .container { + padding: 15px; + } + + .result-card { + padding: 12px; + } + + .score-display { + font-size: 1.8rem; + } + + .meaning-content { + font-size: 0.9rem; + } +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/aimodelapp/AI文章转文言文/index.html b/InfoGenie-frontend/public/aimodelapp/AI文章转文言文/index.html new file mode 100644 index 00000000..7c73e61a --- /dev/null +++ b/InfoGenie-frontend/public/aimodelapp/AI文章转文言文/index.html @@ -0,0 +1,66 @@ + + + + + + AI现代文转文言文助手 + + + +
+
+

AI现代文转文言文助手

+

古韵今声,文白互译

+
+ +
+
+ + +
+ +
+
+ + +
+ +
+ + +
+
+ + +
+ +
+

文言文转换结果

+
正在转换中,请稍候...
+
+
点击"开始转换"按钮,AI将为您提供精准的文言文转换
+
+
+
+ + + + + \ No newline at end of file diff --git a/InfoGenie-frontend/public/aimodelapp/AI文章转文言文/script.js b/InfoGenie-frontend/public/aimodelapp/AI文章转文言文/script.js new file mode 100644 index 00000000..79d427ac --- /dev/null +++ b/InfoGenie-frontend/public/aimodelapp/AI文章转文言文/script.js @@ -0,0 +1,288 @@ +// 从配置文件导入设置 +// 配置在 env.js 文件中定义 + +// DOM 元素 +const modernTextInput = document.getElementById('modernText'); +const styleSelect = document.getElementById('styleSelect'); +const articleTypeSelect = document.getElementById('articleTypeSelect'); +const convertBtn = document.getElementById('convertBtn'); +const loadingDiv = document.getElementById('loading'); +const conversionResultContainer = document.getElementById('conversionResult'); + +// 调用后端API +async function callBackendAPI(modernText, style, articleType) { + try { + const response = await fetch('http://127.0.0.1:5002/api/aimodelapp/classical_conversion', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + modern_text: modernText, + style: style, + article_type: articleType + }) + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.error || `API请求失败: ${response.status} ${response.statusText}`); + } + + const data = await response.json(); + if (data.success) { + return data.conversion_result; + } else { + throw new Error(data.error || 'API响应格式异常'); + } + } catch (error) { + console.error('API调用错误:', error); + throw error; + } +} + +// 解析AI响应 +function parseAIResponse(response) { + try { + // 尝试直接解析JSON + const parsed = JSON.parse(response); + return parsed; + } catch (error) { + // 如果直接解析失败,尝试提取JSON部分 + const jsonMatch = response.match(/\{[\s\S]*\}/); + if (jsonMatch) { + try { + const parsed = JSON.parse(jsonMatch[0]); + return parsed; + } catch (e) { + console.error('JSON解析失败:', e); + } + } + + // 如果JSON解析失败,返回空对象 + console.error('无法解析AI响应:', response); + return {}; + } +} + +// 显示转换结果 +function displayConversionResult(result) { + conversionResultContainer.innerHTML = ''; + + if (!result || !result.classical_text) { + conversionResultContainer.innerHTML = '
转换失败,请尝试重新转换
'; + return; + } + + // 创建结果容器 + const resultDiv = document.createElement('div'); + resultDiv.className = 'conversion-result'; + + // 转换信息 + const infoDiv = document.createElement('div'); + infoDiv.className = 'conversion-info'; + infoDiv.innerHTML = ` +
+ 转换风格: + ${result.style || '经典文言文'} +
+
+ 文章类型: + ${result.article_type || '记叙文'} +
+ `; + resultDiv.appendChild(infoDiv); + + // 原文显示 + const originalDiv = document.createElement('div'); + originalDiv.className = 'original-text'; + originalDiv.innerHTML = ` +
+ 原现代文: + +
+
${result.original_text || modernTextInput.value}
+ `; + resultDiv.appendChild(originalDiv); + + // 文言文结果 + const classicalDiv = document.createElement('div'); + classicalDiv.className = 'classical-text'; + classicalDiv.innerHTML = ` +
+ 文言文转换: + +
+
${result.classical_text}
+ `; + resultDiv.appendChild(classicalDiv); + + // 关键转换说明 + if (result.key_transformations && result.key_transformations.length > 0) { + const transformationsDiv = document.createElement('div'); + transformationsDiv.className = 'transformations'; + transformationsDiv.innerHTML = '
关键转换说明:
'; + + result.key_transformations.forEach((transformation, index) => { + if (transformation && transformation.trim()) { + const transformDiv = document.createElement('div'); + transformDiv.className = 'transformation-item'; + transformDiv.innerHTML = `${index + 1}.${transformation}`; + transformationsDiv.appendChild(transformDiv); + } + }); + + resultDiv.appendChild(transformationsDiv); + } + + // 文言文特色分析 + if (result.classical_features) { + const featuresDiv = document.createElement('div'); + featuresDiv.className = 'classical-features'; + featuresDiv.innerHTML = '
文言文特色分析:
'; + + if (result.classical_features.sentence_patterns) { + const patternDiv = document.createElement('div'); + patternDiv.className = 'feature-item'; + patternDiv.innerHTML = `句式特点:${result.classical_features.sentence_patterns}`; + featuresDiv.appendChild(patternDiv); + } + + if (result.classical_features.vocabulary) { + const vocabDiv = document.createElement('div'); + vocabDiv.className = 'feature-item'; + vocabDiv.innerHTML = `词汇运用:${result.classical_features.vocabulary}`; + featuresDiv.appendChild(vocabDiv); + } + + if (result.classical_features.grammar) { + const grammarDiv = document.createElement('div'); + grammarDiv.className = 'feature-item'; + grammarDiv.innerHTML = `语法特色:${result.classical_features.grammar}`; + featuresDiv.appendChild(grammarDiv); + } + + resultDiv.appendChild(featuresDiv); + } + + // 转换说明 + if (result.explanation) { + const explanationDiv = document.createElement('div'); + explanationDiv.className = 'explanation'; + explanationDiv.innerHTML = `转换说明:
${result.explanation}
`; + resultDiv.appendChild(explanationDiv); + } + + // 发音指导 + if (result.pronunciation_guide) { + const pronunciationDiv = document.createElement('div'); + pronunciationDiv.className = 'pronunciation'; + pronunciationDiv.innerHTML = `古音指导:${result.pronunciation_guide}`; + resultDiv.appendChild(pronunciationDiv); + } + + conversionResultContainer.appendChild(resultDiv); +} + +// 复制到剪贴板 +function copyToClipboard(text) { + navigator.clipboard.writeText(text).then(() => { + showSuccessToast('已复制到剪贴板'); + }).catch(err => { + console.error('复制失败:', err); + // 备用复制方法 + const textArea = document.createElement('textarea'); + textArea.value = text; + document.body.appendChild(textArea); + textArea.select(); + try { + document.execCommand('copy'); + showSuccessToast('已复制到剪贴板'); + } catch (e) { + showErrorMessage('复制失败,请手动复制'); + } + document.body.removeChild(textArea); + }); +} + +// 显示成功提示 +function showSuccessToast(message) { + const toast = document.createElement('div'); + toast.className = 'success-toast'; + toast.textContent = message; + document.body.appendChild(toast); + + setTimeout(() => { + toast.classList.add('show'); + }, 100); + + setTimeout(() => { + toast.classList.remove('show'); + setTimeout(() => { + document.body.removeChild(toast); + }, 300); + }, 2000); +} + +// 显示错误信息 +function showErrorMessage(message) { + const errorDiv = document.createElement('div'); + errorDiv.className = 'error'; + errorDiv.textContent = message; + conversionResultContainer.innerHTML = ''; + conversionResultContainer.appendChild(errorDiv); +} + +// 显示加载状态 +function showLoading(show) { + loadingDiv.style.display = show ? 'block' : 'none'; + convertBtn.disabled = show; + convertBtn.textContent = show ? '转换中...' : '开始转换'; +} + +// 执行转换 +async function performConversion() { + const modernText = modernTextInput.value.trim(); + const style = styleSelect.value; + const articleType = articleTypeSelect.value; + + if (!modernText) { + showErrorMessage('请输入要转换的现代文内容'); + return; + } + + showLoading(true); + conversionResultContainer.innerHTML = ''; + + try { + const result = await callBackendAPI(modernText, style, articleType); + const parsedResult = parseAIResponse(result); + displayConversionResult(parsedResult); + } catch (error) { + console.error('转换失败:', error); + showErrorMessage(`转换失败: ${error.message}`); + } finally { + showLoading(false); + } +} + +// 事件监听器 +convertBtn.addEventListener('click', performConversion); + +// 回车键转换 +modernTextInput.addEventListener('keypress', (e) => { + if (e.key === 'Enter' && e.ctrlKey) { + e.preventDefault(); + performConversion(); + } +}); + +// 页面加载完成后的初始化 +document.addEventListener('DOMContentLoaded', () => { + // 设置默认占位符 + conversionResultContainer.innerHTML = '
请输入现代文内容,选择转换风格和文章类型,然后点击转换按钮
'; +}); + +// 导出函数供HTML调用 +window.copyToClipboard = copyToClipboard; +window.performConversion = performConversion; \ No newline at end of file diff --git a/InfoGenie-frontend/public/aimodelapp/AI文章转文言文/styles.css b/InfoGenie-frontend/public/aimodelapp/AI文章转文言文/styles.css new file mode 100644 index 00000000..8be6fdfe --- /dev/null +++ b/InfoGenie-frontend/public/aimodelapp/AI文章转文言文/styles.css @@ -0,0 +1,603 @@ +/* 全局样式重置 */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +/* 主体样式 - iOS风格 */ +body { + font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Helvetica Neue', Arial, sans-serif; + background: linear-gradient(135deg, #8B4513 0%, #D2691E 50%, #F4A460 100%); + min-height: 100vh; + padding: 20px; + color: #1D1D1F; + line-height: 1.47; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* 容器样式 - iOS毛玻璃效果 */ +.container { + max-width: 900px; + margin: 0 auto; + background: rgba(255, 255, 255, 0.85); + border-radius: 24px; + padding: 32px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.08); + backdrop-filter: blur(20px) saturate(180%); + border: 1px solid rgba(255, 255, 255, 0.2); +} + +/* 头部样式 - iOS风格 */ +.header { + text-align: center; + margin-bottom: 32px; +} + +.title { + font-size: 2.25rem; + color: #8B4513; + margin-bottom: 8px; + font-weight: 600; + letter-spacing: -0.02em; +} + +.subtitle { + color: #D2691E; + font-size: 1.0625rem; + margin-bottom: 24px; + font-weight: 400; +} + +/* 表单样式 - iOS风格 */ +.form-section { + margin-bottom: 32px; +} + +.form-group { + margin-bottom: 24px; +} + +.form-row { + display: flex; + gap: 16px; + margin-bottom: 24px; +} + +.half-width { + flex: 1; +} + +.form-label { + display: block; + margin-bottom: 8px; + font-weight: 600; + color: #1D1D1F; + font-size: 1rem; +} + +.form-input { + width: 100%; + padding: 16px; + border: 1px solid rgba(0, 0, 0, 0.1); + border-radius: 12px; + font-size: 1rem; + transition: all 0.2s ease; + background: rgba(255, 255, 255, 0.8); + font-family: inherit; + backdrop-filter: blur(10px); +} + +.form-input:focus { + outline: none; + border-color: #D2691E; + background: rgba(255, 255, 255, 0.95); + box-shadow: 0 0 0 4px rgba(210, 105, 30, 0.1); +} + +.textarea { + resize: vertical; + min-height: 150px; + font-family: 'SF Mono', 'Monaco', 'Consolas', 'Courier New', monospace; + line-height: 1.6; +} + +.select { + cursor: pointer; + appearance: none; + background-image: url('data:image/svg+xml;charset=US-ASCII,'); + background-repeat: no-repeat; + background-position: right 15px center; + background-size: 12px; + padding-right: 40px; +} + +/* 按钮样式 - iOS风格 */ +.btn { + width: 100%; + padding: 16px; + background: #D2691E; + color: white; + border: none; + border-radius: 12px; + font-size: 1.0625rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(210, 105, 30, 0.25); +} + +.btn:hover { + background: #B8860B; + transform: translateY(-1px); + box-shadow: 0 4px 16px rgba(210, 105, 30, 0.35); +} + +.btn:active { + transform: translateY(0); + background: #A0522D; +} + +.btn:disabled { + opacity: 0.5; + cursor: not-allowed; + transform: none; + background: #86868B; +} + +/* 结果区域样式 - iOS风格 */ +.result-section { + margin-top: 32px; +} + +.result-title { + font-size: 1.25rem; + color: #8B4513; + margin-bottom: 16px; + text-align: center; + font-weight: 600; +} + +.loading { + display: none; + text-align: center; + color: #D2691E; + font-style: normal; + padding: 24px; + font-weight: 500; +} + +.conversion-container { + background: rgba(255, 255, 255, 0.6); + border: 1px solid rgba(0, 0, 0, 0.08); + border-radius: 16px; + padding: 24px; + min-height: 200px; + backdrop-filter: blur(10px); +} + +.placeholder { + text-align: center; + color: #86868B; + font-style: normal; + padding: 40px 20px; + font-weight: 400; +} + +/* 转换结果样式 */ +.conversion-result { + animation: fadeIn 0.3s ease; +} + +.conversion-info { + background: rgba(139, 69, 19, 0.1); + border: 1px solid rgba(139, 69, 19, 0.2); + border-radius: 12px; + padding: 16px; + margin-bottom: 20px; + display: flex; + gap: 24px; + flex-wrap: wrap; +} + +.info-item { + display: flex; + align-items: center; + gap: 8px; +} + +.info-item .label { + font-weight: 600; + color: #8B4513; +} + +.info-item .value { + color: #1D1D1F; + background: rgba(255, 255, 255, 0.8); + padding: 4px 12px; + border-radius: 8px; + font-size: 0.9375rem; +} + +/* 文本显示区域 */ +.original-text, +.classical-text { + background: rgba(255, 255, 255, 0.9); + border: 1px solid rgba(0, 0, 0, 0.06); + border-radius: 12px; + padding: 20px; + margin-bottom: 20px; + position: relative; +} + +.classical-text { + background: rgba(244, 164, 96, 0.1); + border: 1px solid rgba(244, 164, 96, 0.3); +} + +.text-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 12px; +} + +.text-header .label { + font-weight: 600; + color: #1D1D1F; + font-size: 1rem; +} + +.text-content { + font-size: 1.125rem; + color: #1D1D1F; + line-height: 1.8; + font-weight: 400; +} + +.text-content.classical { + font-family: 'STKaiti', 'KaiTi', '楷体', serif; + font-size: 1.25rem; + line-height: 2; + color: #8B4513; + font-weight: 500; +} + +/* 转换说明区域 */ +.transformations { + background: rgba(255, 255, 255, 0.8); + border: 1px solid rgba(0, 0, 0, 0.06); + border-radius: 12px; + padding: 20px; + margin-bottom: 20px; +} + +.transformations-title { + font-weight: 600; + color: #1D1D1F; + margin-bottom: 16px; + font-size: 1rem; +} + +.transformation-item { + display: flex; + align-items: flex-start; + gap: 8px; + padding: 8px 0; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); +} + +.transformation-item:last-child { + border-bottom: none; +} + +.transformation-item .number { + color: #D2691E; + font-weight: 600; + min-width: 20px; +} + +.transformation-item .text { + color: #1D1D1F; + line-height: 1.6; +} + +/* 文言文特色分析 */ +.classical-features { + background: rgba(210, 105, 30, 0.1); + border: 1px solid rgba(210, 105, 30, 0.2); + border-radius: 12px; + padding: 20px; + margin-bottom: 20px; +} + +.features-title { + font-weight: 600; + color: #D2691E; + margin-bottom: 16px; + font-size: 1rem; +} + +.feature-item { + display: flex; + align-items: flex-start; + gap: 12px; + margin-bottom: 12px; +} + +.feature-item:last-child { + margin-bottom: 0; +} + +.feature-label { + font-weight: 600; + color: #8B4513; + min-width: 80px; + font-size: 0.9375rem; +} + +.feature-text { + color: #1D1D1F; + line-height: 1.6; + flex: 1; +} + +.explanation { + background: rgba(139, 69, 19, 0.1); + border: 1px solid rgba(139, 69, 19, 0.2); + border-radius: 12px; + padding: 20px; + margin-bottom: 20px; +} + +.explanation .label { + font-weight: 600; + color: #8B4513; + margin-bottom: 12px; + display: block; +} + +.explanation-text { + color: #1D1D1F; + line-height: 1.6; + font-size: 0.9375rem; +} + +.pronunciation { + background: rgba(255, 149, 0, 0.1); + border: 1px solid rgba(255, 149, 0, 0.2); + border-radius: 12px; + padding: 16px; + margin-bottom: 16px; + font-size: 0.9375rem; +} + +.pronunciation .label { + font-weight: 600; + color: #FF9500; + margin-right: 8px; +} + +.pronunciation .value { + color: #1D1D1F; + font-family: 'SF Mono', 'Monaco', 'Consolas', 'Courier New', monospace; +} + +/* 复制按钮样式 */ +.copy-btn { + background: #D2691E; + color: white; + border: none; + border-radius: 8px; + padding: 8px 16px; + font-size: 0.8125rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: 0 2px 4px rgba(210, 105, 30, 0.25); +} + +.copy-btn:hover { + background: #B8860B; + transform: translateY(-1px); +} + +.copy-btn-small { + background: #D2691E; + color: white; + border: none; + border-radius: 6px; + padding: 4px 8px; + font-size: 0.75rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: 0 1px 2px rgba(210, 105, 30, 0.25); +} + +.copy-btn-small:hover { + background: #B8860B; + transform: translateY(-1px); +} + +/* 错误样式 - iOS风格 */ +.error { + color: #FF3B30; + background: rgba(255, 59, 48, 0.1); + border: 1px solid rgba(255, 59, 48, 0.2); + padding: 16px; + border-radius: 12px; + margin-top: 16px; + font-weight: 500; + backdrop-filter: blur(10px); +} + +/* 成功提示 - iOS风格 */ +.success-toast { + position: fixed; + top: 20px; + right: 20px; + background: #34C759; + color: white; + padding: 12px 20px; + border-radius: 12px; + box-shadow: 0 8px 24px rgba(52, 199, 89, 0.3); + z-index: 1000; + opacity: 0; + transform: translateX(100%); + transition: all 0.3s ease; + font-weight: 600; + backdrop-filter: blur(20px); +} + +.success-toast.show { + opacity: 1; + transform: translateX(0); +} + +/* 响应式设计 */ +@media (max-width: 768px) { + body { + padding: 10px; + } + + .container { + padding: 20px; + margin: 10px; + } + + .title { + font-size: 2rem; + } + + .form-row { + flex-direction: column; + gap: 0; + } + + .form-input { + padding: 12px; + } + + .btn { + padding: 12px; + } + + .conversion-container { + padding: 15px; + } + + .original-text, + .classical-text { + padding: 15px; + } + + .text-header { + flex-direction: column; + align-items: flex-start; + gap: 8px; + } + + .copy-btn { + align-self: flex-end; + } + + .conversion-info { + flex-direction: column; + gap: 12px; + } + + .feature-item { + flex-direction: column; + gap: 4px; + } + + .feature-label { + min-width: auto; + } +} + +@media (max-width: 480px) { + .title { + font-size: 1.8rem; + letter-spacing: 1px; + } + + .container { + padding: 15px; + } + + .form-input { + padding: 10px; + } + + .original-text, + .classical-text { + padding: 12px; + } + + .text-content { + font-size: 1rem; + } + + .text-content.classical { + font-size: 1.125rem; + } +} + +/* 动画效果 */ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.conversion-result { + animation: fadeIn 0.3s ease; +} + +/* 加载动画 */ +@keyframes pulse { + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } +} + +.loading { + animation: pulse 1.5s ease-in-out infinite; +} + +/* 古典风格装饰 */ +.classical-text::before { + content: '「'; + position: absolute; + top: 15px; + left: 15px; + font-size: 1.5rem; + color: #D2691E; + opacity: 0.6; +} + +.classical-text::after { + content: '」'; + position: absolute; + bottom: 15px; + right: 15px; + font-size: 1.5rem; + color: #D2691E; + opacity: 0.6; +} + +.classical-text .text-content { + margin: 0 20px; +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/aimodelapp/AI生成Linux命令/index.html b/InfoGenie-frontend/public/aimodelapp/AI生成Linux命令/index.html new file mode 100644 index 00000000..64b1d030 --- /dev/null +++ b/InfoGenie-frontend/public/aimodelapp/AI生成Linux命令/index.html @@ -0,0 +1,50 @@ + + + + + + AI Linux命令生成器 + + + +
+
+

AI Linux命令生成器

+

让AI为您的Linux操作生成准确的命令

+
+ +
+
+ + +
+ +
+ + +
+ + +
+ +
+

推荐的Linux命令

+
正在生成中,请稍候...
+
+
点击"生成命令"按钮,AI将为您推荐合适的Linux命令
+
+
+
+ + + + + \ No newline at end of file diff --git a/InfoGenie-frontend/public/aimodelapp/AI生成Linux命令/script.js b/InfoGenie-frontend/public/aimodelapp/AI生成Linux命令/script.js new file mode 100644 index 00000000..1a267e4f --- /dev/null +++ b/InfoGenie-frontend/public/aimodelapp/AI生成Linux命令/script.js @@ -0,0 +1,351 @@ +// 从配置文件导入设置 +// 配置在 env.js 文件中定义 + +// DOM 元素 +const taskInput = document.getElementById('task-input'); +const levelSelect = document.getElementById('level-select'); +const generateBtn = document.getElementById('generateBtn'); +const loadingDiv = document.getElementById('loading'); +const commandsContainer = document.getElementById('commands'); + +// 调用后端API +async function callBackendAPI(taskDescription, difficultyLevel) { + try { + const response = await fetch('http://127.0.0.1:5002/api/aimodelapp/linux-command', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + task_description: taskDescription, + difficulty_level: difficultyLevel + }) + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.error || `API请求失败: ${response.status} ${response.statusText}`); + } + + const data = await response.json(); + if (data.success) { + return data.command_result; + } else { + throw new Error(data.error || 'API响应格式异常'); + } + } catch (error) { + console.error('API调用错误:', error); + throw error; + } +} + +// 解析AI响应 +function parseAIResponse(response) { + try { + // 尝试直接解析JSON + const parsed = JSON.parse(response); + return parsed; + } catch (error) { + // 如果直接解析失败,尝试提取JSON部分 + const jsonMatch = response.match(/\{[\s\S]*\}/); + if (jsonMatch) { + try { + const parsed = JSON.parse(jsonMatch[0]); + return parsed; + } catch (e) { + console.error('JSON解析失败:', e); + } + } + + // 如果JSON解析失败,返回空对象 + console.error('无法解析AI响应:', response); + return {}; + } +} + +// 获取安全等级颜色 +function getSafetyLevelColor(safetyLevel) { + const colors = { + 'safe': '#34C759', + 'caution': '#FF9500', + 'dangerous': '#FF3B30' + }; + return colors[safetyLevel] || '#86868B'; +} + +// 获取安全等级文本 +function getSafetyLevelText(safetyLevel) { + const texts = { + 'safe': '安全', + 'caution': '谨慎', + 'dangerous': '危险' + }; + return texts[safetyLevel] || '未知'; +} + +// 显示命令建议 +function displayCommands(commandData) { + commandsContainer.innerHTML = ''; + + if (!commandData || !commandData.commands || commandData.commands.length === 0) { + commandsContainer.innerHTML = '
暂无命令建议,请尝试重新生成
'; + return; + } + + // 显示命令列表 + if (commandData.commands && commandData.commands.length > 0) { + const commandsTitle = document.createElement('div'); + commandsTitle.className = 'section-title'; + commandsTitle.textContent = '推荐命令'; + commandsContainer.appendChild(commandsTitle); + + commandData.commands.forEach((command, index) => { + const commandElement = document.createElement('div'); + commandElement.className = 'command-item'; + + const safetyColor = getSafetyLevelColor(command.safety_level); + const safetyText = getSafetyLevelText(command.safety_level); + + commandElement.innerHTML = ` +
+
+
${command.command}
+
${safetyText}
+
+
${command.description}
+
+ 详细说明:${command.explanation} +
+ ${command.example_output ? `
预期输出:${command.example_output}
` : ''} + ${command.alternatives && command.alternatives.length > 0 ? ` +
+ 替代命令: + ${command.alternatives.map(alt => `${alt}`).join(' ')} +
+ ` : ''} +
+ + `; + commandsContainer.appendChild(commandElement); + }); + } + + // 显示安全警告 + if (commandData.safety_warnings && commandData.safety_warnings.length > 0) { + const warningsTitle = document.createElement('div'); + warningsTitle.className = 'section-title warning'; + warningsTitle.textContent = '⚠️ 安全提示'; + commandsContainer.appendChild(warningsTitle); + + const warningsContainer = document.createElement('div'); + warningsContainer.className = 'warnings-container'; + commandData.safety_warnings.forEach(warning => { + const warningElement = document.createElement('div'); + warningElement.className = 'warning-item'; + warningElement.textContent = warning; + warningsContainer.appendChild(warningElement); + }); + commandsContainer.appendChild(warningsContainer); + } + + // 显示前置条件 + if (commandData.prerequisites && commandData.prerequisites.length > 0) { + const prereqTitle = document.createElement('div'); + prereqTitle.className = 'section-title info'; + prereqTitle.textContent = '📋 前置条件'; + commandsContainer.appendChild(prereqTitle); + + const prereqContainer = document.createElement('div'); + prereqContainer.className = 'prerequisites-container'; + commandData.prerequisites.forEach(prereq => { + const prereqElement = document.createElement('div'); + prereqElement.className = 'prerequisite-item'; + prereqElement.textContent = prereq; + prereqContainer.appendChild(prereqElement); + }); + commandsContainer.appendChild(prereqContainer); + } + + // 显示相关概念 + if (commandData.related_concepts && commandData.related_concepts.length > 0) { + const conceptsTitle = document.createElement('div'); + conceptsTitle.className = 'section-title info'; + conceptsTitle.textContent = '💡 相关概念'; + commandsContainer.appendChild(conceptsTitle); + + const conceptsContainer = document.createElement('div'); + conceptsContainer.className = 'concepts-container'; + commandData.related_concepts.forEach(concept => { + const conceptElement = document.createElement('div'); + conceptElement.className = 'concept-item'; + conceptElement.textContent = concept; + conceptsContainer.appendChild(conceptElement); + }); + commandsContainer.appendChild(conceptsContainer); + } +} + +// 复制到剪贴板 +function copyToClipboard(text, button) { + navigator.clipboard.writeText(text).then(() => { + showSuccessToast('已复制到剪贴板'); + const originalText = button.textContent; + button.textContent = '已复制'; + button.classList.add('copied'); + setTimeout(() => { + button.textContent = originalText; + button.classList.remove('copied'); + }, 2000); + }).catch(err => { + console.error('复制失败:', err); + // 备用复制方法 + const textArea = document.createElement('textarea'); + textArea.value = text; + document.body.appendChild(textArea); + textArea.select(); + try { + document.execCommand('copy'); + showSuccessToast('已复制到剪贴板'); + const originalText = button.textContent; + button.textContent = '已复制'; + button.classList.add('copied'); + setTimeout(() => { + button.textContent = originalText; + button.classList.remove('copied'); + }, 2000); + } catch (e) { + showErrorMessage('复制失败,请手动复制'); + } + document.body.removeChild(textArea); + }); +} + +// 显示成功提示 +function showSuccessToast(message) { + const toast = document.createElement('div'); + toast.className = 'success-toast'; + toast.textContent = message; + document.body.appendChild(toast); + + setTimeout(() => { + toast.classList.add('show'); + }, 100); + + setTimeout(() => { + toast.classList.remove('show'); + setTimeout(() => { + document.body.removeChild(toast); + }, 300); + }, 2000); +} + +// 显示错误信息 +function showErrorMessage(message) { + const errorDiv = document.createElement('div'); + errorDiv.className = 'error'; + errorDiv.textContent = message; + commandsContainer.innerHTML = ''; + commandsContainer.appendChild(errorDiv); +} + +// 显示加载状态 +function showLoading(show) { + loadingDiv.style.display = show ? 'block' : 'none'; + generateBtn.disabled = show; + generateBtn.textContent = show ? '生成中...' : '生成命令'; +} + +// 生成命令建议 +async function generateCommands() { + const taskDescription = taskInput.value.trim(); + const difficultyLevel = levelSelect.value; + + if (!taskDescription) { + showErrorMessage('请输入任务描述'); + return; + } + + showLoading(true); + commandsContainer.innerHTML = ''; + + try { + const commandResult = await callBackendAPI(taskDescription, difficultyLevel); + const commandData = parseAIResponse(commandResult); + displayCommands(commandData); + } catch (error) { + console.error('生成命令失败:', error); + showErrorMessage(`生成失败: ${error.message}`); + } finally { + showLoading(false); + } +} + +// 事件监听器 +generateBtn.addEventListener('click', generateCommands); + +// 回车键生成 +taskInput.addEventListener('keypress', (e) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + generateCommands(); + } +}); + +// 技能水平变化时的提示 +levelSelect.addEventListener('change', (e) => { + const levelDescriptions = { + 'beginner': '将提供基础命令和详细解释', + 'intermediate': '将提供常用命令和选项', + 'advanced': '将提供高效命令和高级用法' + }; + + const description = levelDescriptions[e.target.value]; + if (description) { + console.log(`已选择技能水平: ${e.target.value} - ${description}`); + } +}); + +// 页面加载完成后的初始化 +document.addEventListener('DOMContentLoaded', () => { + // 设置默认占位符 + commandsContainer.innerHTML = '
请输入要执行的Linux操作,然后点击生成按钮获取相应的命令
'; + + // 设置默认任务描述 + if (!taskInput.value.trim()) { + taskInput.value = '切换到根目录'; + } +}); + +// 导出函数供HTML调用 +window.copyToClipboard = copyToClipboard; +window.generateCommands = generateCommands; + +// 添加一些实用的辅助函数 +function getRandomCommand(commands) { + if (commands && commands.length > 0) { + const randomIndex = Math.floor(Math.random() * commands.length); + return commands[randomIndex]; + } + return null; +} + +// 命令使用统计(可选功能) +function trackCommandUsage(command) { + const usage = JSON.parse(localStorage.getItem('commandUsage') || '{}'); + usage[command] = (usage[command] || 0) + 1; + localStorage.setItem('commandUsage', JSON.stringify(usage)); +} + +// 获取常用命令(可选功能) +function getPopularCommands(limit = 5) { + const usage = JSON.parse(localStorage.getItem('commandUsage') || '{}'); + return Object.entries(usage) + .sort(([,a], [,b]) => b - a) + .slice(0, limit) + .map(([command]) => command); +} + +// 导出辅助函数 +window.getRandomCommand = getRandomCommand; +window.trackCommandUsage = trackCommandUsage; +window.getPopularCommands = getPopularCommands; \ No newline at end of file diff --git a/InfoGenie-frontend/public/aimodelapp/AI生成Linux命令/styles.css b/InfoGenie-frontend/public/aimodelapp/AI生成Linux命令/styles.css new file mode 100644 index 00000000..0761c4c5 --- /dev/null +++ b/InfoGenie-frontend/public/aimodelapp/AI生成Linux命令/styles.css @@ -0,0 +1,576 @@ +/* 全局样式重置 */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +/* 主体样式 - iOS风格 */ +body { + font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Helvetica Neue', Arial, sans-serif; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + min-height: 100vh; + padding: 20px; + color: #1D1D1F; + line-height: 1.47; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* 容器样式 - iOS毛玻璃效果 */ +.container { + max-width: 900px; + margin: 0 auto; + background: rgba(255, 255, 255, 0.85); + border-radius: 24px; + padding: 32px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.08); + backdrop-filter: blur(20px) saturate(180%); + border: 1px solid rgba(255, 255, 255, 0.2); +} + +/* 头部样式 - iOS风格 */ +.header { + text-align: center; + margin-bottom: 32px; +} + +.title { + font-size: 2.25rem; + color: #1D1D1F; + margin-bottom: 8px; + font-weight: 600; + letter-spacing: -0.02em; +} + +.subtitle { + color: #86868B; + font-size: 1.0625rem; + margin-bottom: 24px; + font-weight: 400; +} + +/* 表单样式 - iOS风格 */ +.form-section { + margin-bottom: 32px; +} + +.form-group { + margin-bottom: 24px; +} + +.form-label { + display: block; + margin-bottom: 8px; + font-weight: 600; + color: #1D1D1F; + font-size: 1rem; +} + +.form-input { + width: 100%; + padding: 16px; + border: 1px solid rgba(0, 0, 0, 0.1); + border-radius: 12px; + font-size: 1rem; + transition: all 0.2s ease; + background: rgba(255, 255, 255, 0.8); + font-family: inherit; + backdrop-filter: blur(10px); +} + +.form-input:focus { + outline: none; + border-color: #667eea; + background: rgba(255, 255, 255, 0.95); + box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.1); +} + +.textarea { + resize: vertical; + min-height: 120px; +} + +.select { + cursor: pointer; + appearance: none; + background-image: url('data:image/svg+xml;charset=US-ASCII,'); + background-repeat: no-repeat; + background-position: right 15px center; + background-size: 12px; + padding-right: 40px; +} + +/* 按钮样式 - iOS风格 */ +.btn { + width: 100%; + padding: 16px; + background: #667eea; + color: white; + border: none; + border-radius: 12px; + font-size: 1.0625rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(102, 126, 234, 0.25); +} + +.btn:hover { + background: #5a67d8; + transform: translateY(-1px); + box-shadow: 0 4px 16px rgba(102, 126, 234, 0.35); +} + +.btn:active { + transform: translateY(0); + background: #4c51bf; +} + +.btn:disabled { + opacity: 0.5; + cursor: not-allowed; + transform: none; + background: #86868B; +} + +/* 结果区域样式 - iOS风格 */ +.result-section { + margin-top: 32px; +} + +.result-title { + font-size: 1.25rem; + color: #1D1D1F; + margin-bottom: 16px; + text-align: center; + font-weight: 600; +} + +.loading { + display: none; + text-align: center; + color: #667eea; + font-style: normal; + padding: 24px; + font-weight: 500; +} + +.commands-container { + background: rgba(255, 255, 255, 0.6); + border: 1px solid rgba(0, 0, 0, 0.08); + border-radius: 16px; + padding: 24px; + min-height: 150px; + backdrop-filter: blur(10px); +} + +.placeholder { + text-align: center; + color: #86868B; + font-style: normal; + padding: 40px 20px; + font-weight: 400; +} + +/* 分组标题样式 - iOS风格 */ +.section-title { + font-size: 1.125rem; + font-weight: 600; + color: white; + margin: 20px 0 12px 0; + padding: 12px 16px; + background: #667eea; + border-radius: 12px; + text-align: center; + box-shadow: 0 2px 8px rgba(102, 126, 234, 0.25); +} + +.section-title:first-child { + margin-top: 0; +} + +.section-title.warning { + background: #FF9500; + box-shadow: 0 2px 8px rgba(255, 149, 0, 0.25); +} + +.section-title.info { + background: #34C759; + box-shadow: 0 2px 8px rgba(52, 199, 89, 0.25); +} + +/* 命令项样式 - iOS风格 */ +.command-item { + background: rgba(255, 255, 255, 0.9); + border: 1px solid rgba(0, 0, 0, 0.06); + border-radius: 12px; + padding: 20px; + margin-bottom: 16px; + transition: all 0.2s ease; + position: relative; + backdrop-filter: blur(10px); +} + +.command-item:hover { + border-color: rgba(102, 126, 234, 0.3); + box-shadow: 0 4px 16px rgba(102, 126, 234, 0.1); + background: rgba(255, 255, 255, 0.95); +} + +.command-item:last-child { + margin-bottom: 0; +} + +.command-content { + margin-bottom: 16px; +} + +.command-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 12px; + flex-wrap: wrap; + gap: 8px; +} + +.command-code { + font-family: 'SF Mono', 'Monaco', 'Consolas', 'Courier New', monospace; + background: #f8f9fa; + padding: 8px 12px; + border-radius: 8px; + font-size: 0.9375rem; + color: #2d3748; + border: 1px solid #e2e8f0; + flex: 1; + min-width: 0; + word-break: break-all; +} + +.safety-badge { + padding: 4px 12px; + border-radius: 20px; + font-size: 0.8125rem; + font-weight: 600; + color: white; + white-space: nowrap; +} + +.command-description { + font-size: 1rem; + color: #2d3748; + margin-bottom: 12px; + line-height: 1.5; +} + +.command-explanation { + font-size: 0.9375rem; + color: #4a5568; + margin-bottom: 12px; + line-height: 1.5; +} + +.command-output { + margin-bottom: 12px; +} + +.command-output code { + font-family: 'SF Mono', 'Monaco', 'Consolas', 'Courier New', monospace; + background: #2d3748; + color: #e2e8f0; + padding: 8px 12px; + border-radius: 6px; + font-size: 0.875rem; + display: block; + margin-top: 4px; + white-space: pre-wrap; + word-break: break-all; +} + +.command-alternatives { + margin-top: 12px; +} + +.alt-command { + font-family: 'SF Mono', 'Monaco', 'Consolas', 'Courier New', monospace; + background: #e2e8f0; + color: #2d3748; + padding: 4px 8px; + border-radius: 4px; + font-size: 0.8125rem; + margin: 2px 4px 2px 0; + display: inline-block; + cursor: pointer; + transition: all 0.2s ease; +} + +.alt-command:hover { + background: #cbd5e0; + transform: translateY(-1px); +} + +.copy-btn { + background: #667eea; + color: white; + border: none; + border-radius: 8px; + padding: 10px 20px; + font-size: 0.875rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: 0 2px 4px rgba(102, 126, 234, 0.25); + position: absolute; + top: 20px; + right: 20px; +} + +.copy-btn:hover { + background: #5a67d8; + transform: translateY(-1px); +} + +.copy-btn.copied { + background: #34C759; +} + +/* 警告容器样式 */ +.warnings-container { + margin-bottom: 16px; +} + +.warning-item { + background: rgba(255, 149, 0, 0.1); + border: 1px solid rgba(255, 149, 0, 0.2); + border-radius: 8px; + padding: 12px 16px; + margin-bottom: 8px; + color: #b45309; + font-size: 0.9375rem; + line-height: 1.5; +} + +.warning-item:last-child { + margin-bottom: 0; +} + +/* 前置条件容器样式 */ +.prerequisites-container { + margin-bottom: 16px; +} + +.prerequisite-item { + background: rgba(52, 199, 89, 0.1); + border: 1px solid rgba(52, 199, 89, 0.2); + border-radius: 8px; + padding: 12px 16px; + margin-bottom: 8px; + color: #166534; + font-size: 0.9375rem; + line-height: 1.5; +} + +.prerequisite-item:last-child { + margin-bottom: 0; +} + +/* 相关概念容器样式 */ +.concepts-container { + margin-bottom: 16px; +} + +.concept-item { + background: rgba(59, 130, 246, 0.1); + border: 1px solid rgba(59, 130, 246, 0.2); + border-radius: 8px; + padding: 12px 16px; + margin-bottom: 8px; + color: #1e40af; + font-size: 0.9375rem; + line-height: 1.5; +} + +.concept-item:last-child { + margin-bottom: 0; +} + +/* 错误样式 - iOS风格 */ +.error { + color: #FF3B30; + background: rgba(255, 59, 48, 0.1); + border: 1px solid rgba(255, 59, 48, 0.2); + padding: 16px; + border-radius: 12px; + margin-top: 16px; + font-weight: 500; + backdrop-filter: blur(10px); +} + +/* 成功提示 - iOS风格 */ +.success-toast { + position: fixed; + top: 20px; + right: 20px; + background: #34C759; + color: white; + padding: 12px 20px; + border-radius: 12px; + box-shadow: 0 8px 24px rgba(52, 199, 89, 0.3); + z-index: 1000; + opacity: 0; + transform: translateX(100%); + transition: all 0.3s ease; + font-weight: 600; + backdrop-filter: blur(20px); +} + +.success-toast.show { + opacity: 1; + transform: translateX(0); +} + +/* 响应式设计 - 移动端优化 */ +@media (max-width: 768px) { + body { + padding: 16px; + } + + .container { + padding: 24px; + border-radius: 20px; + } + + .title { + font-size: 1.875rem; + } + + .subtitle { + font-size: 1rem; + } + + .form-input { + padding: 14px; + font-size: 1rem; + } + + .btn { + padding: 16px; + font-size: 1rem; + } + + .commands-container { + padding: 20px; + } + + .command-item { + padding: 16px; + margin-bottom: 16px; + } + + .command-header { + flex-direction: column; + align-items: stretch; + } + + .command-code { + margin-bottom: 8px; + font-size: 0.875rem; + } + + .copy-btn { + position: static; + width: 100%; + margin-top: 12px; + } + + .safety-badge { + align-self: flex-start; + } +} + +@media (max-width: 480px) { + .title { + font-size: 1.75rem; + } + + .container { + padding: 20px; + } + + .form-input { + padding: 12px; + } + + .command-item { + padding: 12px; + } + + .command-code { + font-size: 0.8125rem; + padding: 6px 8px; + } + + .command-description, + .command-explanation { + font-size: 0.875rem; + } +} + +/* 动画效果 */ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.command-item { + animation: fadeIn 0.3s ease; +} + +/* 加载动画 */ +@keyframes pulse { + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } +} + +.loading { + animation: pulse 1.5s ease-in-out infinite; +} + +/* 代码字体优化 */ +.command-code, +.alt-command, +code { + font-family: 'SF Mono', 'Monaco', 'Consolas', 'Courier New', monospace; + font-variant-ligatures: none; +} + +/* 滚动条样式 */ +::-webkit-scrollbar { + width: 8px; +} + +::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0.1); + border-radius: 4px; +} + +::-webkit-scrollbar-thumb { + background: rgba(102, 126, 234, 0.3); + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: rgba(102, 126, 234, 0.5); +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/aimodelapp/AI生成表情包/index.html b/InfoGenie-frontend/public/aimodelapp/AI生成表情包/index.html new file mode 100644 index 00000000..9ce56643 --- /dev/null +++ b/InfoGenie-frontend/public/aimodelapp/AI生成表情包/index.html @@ -0,0 +1,52 @@ + + + + + + AI表情制作器 + + + +
+
+

AI表情制作器

+

让AI为您的文字生成生动的表情符号

+
+ +
+
+ + +
+ +
+ + +
+ + +
+ +
+

推荐的表情

+
正在生成中,请稍候...
+
+
点击"生成表情"按钮,AI将为您推荐合适的表情符号
+
+
+
+ + + + + \ No newline at end of file diff --git a/InfoGenie-frontend/public/aimodelapp/AI生成表情包/script.js b/InfoGenie-frontend/public/aimodelapp/AI生成表情包/script.js new file mode 100644 index 00000000..8afea55e --- /dev/null +++ b/InfoGenie-frontend/public/aimodelapp/AI生成表情包/script.js @@ -0,0 +1,298 @@ +// 从配置文件导入设置 +// 配置在 env.js 文件中定义 + +// DOM 元素 +const textInput = document.getElementById('text-input'); +const styleSelect = document.getElementById('style-select'); +const generateBtn = document.getElementById('generateBtn'); +const loadingDiv = document.getElementById('loading'); +const expressionsContainer = document.getElementById('expressions'); + +// 调用后端API +async function callBackendAPI(text, style) { + try { + const response = await fetch('http://127.0.0.1:5002/api/aimodelapp/expression-maker', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + text: text, + style: style + }) + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.error || `API请求失败: ${response.status} ${response.statusText}`); + } + + const data = await response.json(); + if (data.success) { + return data.expressions; + } else { + throw new Error(data.error || 'API响应格式异常'); + } + } catch (error) { + console.error('API调用错误:', error); + throw error; + } +} + +// 解析AI响应 +function parseAIResponse(response) { + try { + // 尝试直接解析JSON + const parsed = JSON.parse(response); + return parsed.expressions || {}; + } catch (error) { + // 如果直接解析失败,尝试提取JSON部分 + const jsonMatch = response.match(/\{[\s\S]*\}/); + if (jsonMatch) { + try { + const parsed = JSON.parse(jsonMatch[0]); + return parsed.expressions || {}; + } catch (e) { + console.error('JSON解析失败:', e); + } + } + + // 如果JSON解析失败,返回空对象 + console.error('无法解析AI响应:', response); + return {}; + } +} + +// 显示表情建议 +function displayExpressions(expressions) { + expressionsContainer.innerHTML = ''; + + if (!expressions || Object.keys(expressions).length === 0) { + expressionsContainer.innerHTML = '
暂无表情建议,请尝试重新生成
'; + return; + } + + // 表情分类的显示名称 + const categoryNames = { + 'emoji': 'Emoji表情', + 'kaomoji': '颜文字', + 'combination': '组合表情' + }; + + // 按分类显示表情 + Object.keys(expressions).forEach(category => { + if (expressions[category] && expressions[category].length > 0) { + // 创建分组标题 + const groupTitle = document.createElement('div'); + groupTitle.className = 'expression-group-title'; + groupTitle.textContent = categoryNames[category] || category; + expressionsContainer.appendChild(groupTitle); + + // 显示该分类下的表情 + expressions[category].forEach(expression => { + const expressionElement = document.createElement('div'); + expressionElement.className = 'expression-item'; + + // 获取情感强度颜色 + const intensityColor = CONFIG.intensityLevels[expression.intensity]?.color || '#86868B'; + + expressionElement.innerHTML = ` +
+
${expression.symbol}
+
+
${expression.symbol}
+
+ ${expression.description}
+ 强度: ${expression.intensity} + ${expression.usage ? ` | ${expression.usage}` : ''} +
+
+
+ + `; + expressionsContainer.appendChild(expressionElement); + }); + } + }); +} + +// 复制到剪贴板 +function copyToClipboard(text, button) { + navigator.clipboard.writeText(text).then(() => { + showSuccessToast('已复制到剪贴板'); + button.textContent = '已复制'; + setTimeout(() => { + button.textContent = '复制'; + }, 2000); + }).catch(err => { + console.error('复制失败:', err); + // 备用复制方法 + const textArea = document.createElement('textarea'); + textArea.value = text; + document.body.appendChild(textArea); + textArea.select(); + try { + document.execCommand('copy'); + showSuccessToast('已复制到剪贴板'); + button.textContent = '已复制'; + setTimeout(() => { + button.textContent = '复制'; + }, 2000); + } catch (e) { + showErrorMessage('复制失败,请手动复制'); + } + document.body.removeChild(textArea); + }); +} + +// 显示成功提示 +function showSuccessToast(message) { + const toast = document.createElement('div'); + toast.className = 'success-toast'; + toast.textContent = message; + document.body.appendChild(toast); + + setTimeout(() => { + toast.classList.add('show'); + }, 100); + + setTimeout(() => { + toast.classList.remove('show'); + setTimeout(() => { + document.body.removeChild(toast); + }, 300); + }, 2000); +} + +// 显示错误信息 +function showErrorMessage(message) { + const errorDiv = document.createElement('div'); + errorDiv.className = 'error'; + errorDiv.textContent = message; + expressionsContainer.innerHTML = ''; + expressionsContainer.appendChild(errorDiv); +} + +// 显示加载状态 +function showLoading(show) { + loadingDiv.style.display = show ? 'block' : 'none'; + generateBtn.disabled = show; + generateBtn.textContent = show ? '生成中...' : '生成表情'; +} + +// 生成表情建议 +async function generateExpressions() { + const text = textInput.value.trim(); + const style = styleSelect.value; + + if (!text) { + showErrorMessage('请输入要表达的文字内容'); + return; + } + + showLoading(true); + expressionsContainer.innerHTML = ''; + + try { + const expressions = await callBackendAPI(text, style); + displayExpressions(expressions); + } catch (error) { + console.error('生成表情失败:', error); + showErrorMessage(`生成失败: ${error.message}`); + } finally { + showLoading(false); + } +} + +// 初始化样式选择器 +function initializeStyleSelector() { + // 清空现有选项 + styleSelect.innerHTML = ''; + + // 添加样式选项 + Object.keys(CONFIG.expressionStyles).forEach(styleKey => { + const option = document.createElement('option'); + option.value = styleKey; + option.textContent = `${CONFIG.expressionStyles[styleKey].name} - ${CONFIG.expressionStyles[styleKey].description}`; + styleSelect.appendChild(option); + }); + + // 设置默认选项 + styleSelect.value = 'mixed'; +} + +// 事件监听器 +generateBtn.addEventListener('click', generateExpressions); + +// 回车键生成 +textInput.addEventListener('keypress', (e) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + generateExpressions(); + } +}); + +// 样式选择变化时的提示 +styleSelect.addEventListener('change', (e) => { + const selectedStyle = CONFIG.expressionStyles[e.target.value]; + if (selectedStyle) { + // 可以在这里添加样式变化的提示 + console.log(`已选择样式: ${selectedStyle.name} - ${selectedStyle.description}`); + } +}); + +// 页面加载完成后的初始化 +document.addEventListener('DOMContentLoaded', () => { + // 初始化样式选择器 + initializeStyleSelector(); + + // 设置默认占位符 + expressionsContainer.innerHTML = '
请输入要表达的文字,然后点击生成按钮获取相应的表情符号
'; + + // 设置默认文本 + if (!textInput.value.trim()) { + textInput.value = '开心'; + } +}); + +// 导出函数供HTML调用 +window.copyToClipboard = copyToClipboard; +window.generateExpressions = generateExpressions; + +// 添加一些实用的辅助函数 +function getRandomExpression(expressions) { + const allExpressions = []; + Object.values(expressions).forEach(categoryExpressions => { + if (Array.isArray(categoryExpressions)) { + allExpressions.push(...categoryExpressions); + } + }); + + if (allExpressions.length > 0) { + const randomIndex = Math.floor(Math.random() * allExpressions.length); + return allExpressions[randomIndex]; + } + + return null; +} + +// 表情使用统计(可选功能) +function trackExpressionUsage(expression) { + const usage = JSON.parse(localStorage.getItem('expressionUsage') || '{}'); + usage[expression] = (usage[expression] || 0) + 1; + localStorage.setItem('expressionUsage', JSON.stringify(usage)); +} + +// 获取常用表情(可选功能) +function getPopularExpressions(limit = 5) { + const usage = JSON.parse(localStorage.getItem('expressionUsage') || '{}'); + return Object.entries(usage) + .sort(([,a], [,b]) => b - a) + .slice(0, limit) + .map(([expression]) => expression); +} + +// 导出辅助函数 +window.getRandomExpression = getRandomExpression; +window.trackExpressionUsage = trackExpressionUsage; +window.getPopularExpressions = getPopularExpressions; \ No newline at end of file diff --git a/InfoGenie-frontend/public/aimodelapp/AI生成表情包/styles.css b/InfoGenie-frontend/public/aimodelapp/AI生成表情包/styles.css new file mode 100644 index 00000000..54689967 --- /dev/null +++ b/InfoGenie-frontend/public/aimodelapp/AI生成表情包/styles.css @@ -0,0 +1,436 @@ +/* 全局样式重置 */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +/* 主体样式 - iOS风格 */ +body { + font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Helvetica Neue', Arial, sans-serif; + background: linear-gradient(135deg, #FFB6C1 0%, #FFE4E1 100%); + min-height: 100vh; + padding: 20px; + color: #1D1D1F; + line-height: 1.47; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* 容器样式 - iOS毛玻璃效果 */ +.container { + max-width: 700px; + margin: 0 auto; + background: rgba(255, 255, 255, 0.85); + border-radius: 24px; + padding: 32px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.08); + backdrop-filter: blur(20px) saturate(180%); + border: 1px solid rgba(255, 255, 255, 0.2); +} + +/* 头部样式 - iOS风格 */ +.header { + text-align: center; + margin-bottom: 32px; +} + +.title { + font-size: 2.25rem; + color: #1D1D1F; + margin-bottom: 8px; + font-weight: 600; + letter-spacing: -0.02em; +} + +.subtitle { + color: #86868B; + font-size: 1.0625rem; + margin-bottom: 24px; + font-weight: 400; +} + +/* 表单样式 - iOS风格 */ +.form-section { + margin-bottom: 32px; +} + +.form-group { + margin-bottom: 24px; +} + +.form-label { + display: block; + margin-bottom: 8px; + font-weight: 600; + color: #1D1D1F; + font-size: 1rem; +} + +.form-input { + width: 100%; + padding: 16px; + border: 1px solid rgba(0, 0, 0, 0.1); + border-radius: 12px; + font-size: 1rem; + transition: all 0.2s ease; + background: rgba(255, 255, 255, 0.8); + font-family: inherit; + backdrop-filter: blur(10px); +} + +.form-input:focus { + outline: none; + border-color: #FF69B4; + background: rgba(255, 255, 255, 0.95); + box-shadow: 0 0 0 4px rgba(255, 105, 180, 0.1); +} + +.textarea { + resize: vertical; + min-height: 120px; +} + +.select { + cursor: pointer; + appearance: none; + background-image: url('data:image/svg+xml;charset=US-ASCII,'); + background-repeat: no-repeat; + background-position: right 15px center; + background-size: 12px; + padding-right: 40px; +} + +/* 按钮样式 - iOS风格 */ +.btn { + width: 100%; + padding: 16px; + background: #FF69B4; + color: white; + border: none; + border-radius: 12px; + font-size: 1.0625rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(255, 105, 180, 0.25); +} + +.btn:hover { + background: #FF1493; + transform: translateY(-1px); + box-shadow: 0 4px 16px rgba(255, 105, 180, 0.35); +} + +.btn:active { + transform: translateY(0); + background: #DC143C; +} + +.btn:disabled { + opacity: 0.5; + cursor: not-allowed; + transform: none; + background: #86868B; +} + +/* 结果区域样式 - iOS风格 */ +.result-section { + margin-top: 32px; +} + +.result-title { + font-size: 1.25rem; + color: #1D1D1F; + margin-bottom: 16px; + text-align: center; + font-weight: 600; +} + +.loading { + display: none; + text-align: center; + color: #FF69B4; + font-style: normal; + padding: 24px; + font-weight: 500; +} + +.expressions-container { + background: rgba(255, 255, 255, 0.6); + border: 1px solid rgba(0, 0, 0, 0.08); + border-radius: 16px; + padding: 24px; + min-height: 150px; + backdrop-filter: blur(10px); +} + +.placeholder { + text-align: center; + color: #86868B; + font-style: normal; + padding: 40px 20px; + font-weight: 400; +} + +/* 表情分组标题样式 - iOS风格 */ +.expression-group-title { + font-size: 1.0625rem; + font-weight: 600; + color: white; + margin: 20px 0 12px 0; + padding: 12px 16px; + background: #FF69B4; + border-radius: 12px; + text-align: center; + box-shadow: 0 2px 8px rgba(255, 105, 180, 0.25); +} + +.expression-group-title:first-child { + margin-top: 0; +} + +/* 表情项样式 - iOS风格 */ +.expression-item { + background: rgba(255, 255, 255, 0.9); + border: 1px solid rgba(0, 0, 0, 0.06); + border-radius: 12px; + padding: 16px; + margin-bottom: 12px; + transition: all 0.2s ease; + cursor: pointer; + position: relative; + backdrop-filter: blur(10px); + display: flex; + flex-direction: column; + align-items: center; +} + +.expression-item:hover { + border-color: rgba(255, 105, 180, 0.3); + box-shadow: 0 4px 16px rgba(255, 105, 180, 0.1); + background: rgba(255, 255, 255, 0.95); +} + +.expression-item:last-child { + margin-bottom: 0; +} + +.expression-content { + display: flex; + flex-direction: column; + align-items: center; + width: 100%; + text-align: center; +} + +.expression-symbol { + font-size: 2.5rem; + margin-bottom: 12px; + line-height: 1; +} + +.expression-info { + width: 100%; + text-align: center; +} + +.expression-text { + display: none; +} + +.expression-description { + font-size: 0.9375rem; + color: #86868B; + line-height: 1.47; + margin-bottom: 12px; +} + +.copy-btn { + background: #FF69B4; + color: white; + border: none; + border-radius: 8px; + padding: 8px 16px; + font-size: 0.8125rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: 0 2px 4px rgba(255, 105, 180, 0.25); + margin-top: 8px; + align-self: center; +} + +.copy-btn:hover { + background: #FF1493; + transform: translateY(-1px); +} + +/* 错误样式 - iOS风格 */ +.error { + color: #FF3B30; + background: rgba(255, 59, 48, 0.1); + border: 1px solid rgba(255, 59, 48, 0.2); + padding: 16px; + border-radius: 12px; + margin-top: 16px; + font-weight: 500; + backdrop-filter: blur(10px); +} + +/* 成功提示 - iOS风格 */ +.success-toast { + position: fixed; + top: 20px; + right: 20px; + background: #34C759; + color: white; + padding: 12px 20px; + border-radius: 12px; + box-shadow: 0 8px 24px rgba(52, 199, 89, 0.3); + z-index: 1000; + opacity: 0; + transform: translateX(100%); + transition: all 0.3s ease; + font-weight: 600; + backdrop-filter: blur(20px); +} + +.success-toast.show { + opacity: 1; + transform: translateX(0); +} + +/* 响应式设计 - 移动端优化 */ +@media (max-width: 768px) { + body { + padding: 16px; + } + + .container { + padding: 24px; + border-radius: 20px; + } + + .title { + font-size: 1.875rem; + } + + .subtitle { + font-size: 1rem; + } + + .form-input { + padding: 14px; + font-size: 1rem; + } + + .btn { + padding: 16px; + font-size: 1rem; + } + + .expressions-container { + padding: 20px; + } + + .expression-item { + padding: 16px; + margin-bottom: 16px; + } + + .expression-content { + width: 100%; + margin-bottom: 8px; + } + + .expression-symbol { + font-size: 3rem; + margin-bottom: 16px; + } + + .expression-description { + font-size: 0.875rem; + margin-bottom: 16px; + padding: 0 8px; + } + + .copy-btn { + padding: 10px 20px; + font-size: 0.875rem; + margin-top: 12px; + width: 100%; + } +} + +@media (max-width: 480px) { + .title { + font-size: 1.8rem; + letter-spacing: 1px; + } + + .container { + padding: 15px; + } + + .form-input { + padding: 10px; + } + + .expression-item { + padding: 10px; + } + + .expression-text { + font-size: 1rem; + } + + .expression-description { + font-size: 0.85rem; + } + + .expression-symbol { + font-size: 1.2rem; + } +} + +/* 动画效果 */ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.expression-item { + animation: fadeIn 0.3s ease; +} + +/* 加载动画 */ +@keyframes pulse { + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } +} + +.loading { + animation: pulse 1.5s ease-in-out infinite; +} + +/* 表情符号特殊样式 */ +.emoji { + font-family: 'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji', sans-serif; +} + +.kaomoji { + font-family: 'SF Mono', 'Monaco', 'Consolas', 'Courier New', monospace; + font-weight: normal; +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/aimodelapp/AI语言翻译助手/index.html b/InfoGenie-frontend/public/aimodelapp/AI语言翻译助手/index.html new file mode 100644 index 00000000..6e3d53e0 --- /dev/null +++ b/InfoGenie-frontend/public/aimodelapp/AI语言翻译助手/index.html @@ -0,0 +1,62 @@ + + + + + + AI语言翻译助手 + + + +
+
+

AI语言翻译助手

+

智能翻译,信达雅兼备

+
+ +
+
+ + +
+ +
+ + +
+ + +
+ +
+

翻译结果

+
正在翻译中,请稍候...
+
+
点击"开始翻译"按钮,AI将为您提供高质量的翻译结果
+
+
+
+ + + + + \ No newline at end of file diff --git a/InfoGenie-frontend/public/aimodelapp/AI语言翻译助手/script.js b/InfoGenie-frontend/public/aimodelapp/AI语言翻译助手/script.js new file mode 100644 index 00000000..535cc287 --- /dev/null +++ b/InfoGenie-frontend/public/aimodelapp/AI语言翻译助手/script.js @@ -0,0 +1,239 @@ +// 从配置文件导入设置 +// 配置在 env.js 文件中定义 + +// DOM 元素 +const sourceTextInput = document.getElementById('sourceText'); +const targetLanguageSelect = document.getElementById('targetLanguage'); +const translateBtn = document.getElementById('translateBtn'); +const loadingDiv = document.getElementById('loading'); +const translationResultContainer = document.getElementById('translationResult'); + +// 调用后端API +async function callBackendAPI(sourceText, targetLanguage) { + try { + const response = await fetch('http://127.0.0.1:5002/api/aimodelapp/translation', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + source_text: sourceText, + target_language: targetLanguage + }) + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.error || `API请求失败: ${response.status} ${response.statusText}`); + } + + const data = await response.json(); + if (data.success) { + return data.translation_result; + } else { + throw new Error(data.error || 'API响应格式异常'); + } + } catch (error) { + console.error('API调用错误:', error); + throw error; + } +} + +// 解析AI响应 +function parseAIResponse(response) { + try { + // 尝试直接解析JSON + const parsed = JSON.parse(response); + return parsed; + } catch (error) { + // 如果直接解析失败,尝试提取JSON部分 + const jsonMatch = response.match(/\{[\s\S]*\}/); + if (jsonMatch) { + try { + const parsed = JSON.parse(jsonMatch[0]); + return parsed; + } catch (e) { + console.error('JSON解析失败:', e); + } + } + + // 如果JSON解析失败,返回空对象 + console.error('无法解析AI响应:', response); + return {}; + } +} + +// 显示翻译结果 +function displayTranslationResult(result) { + translationResultContainer.innerHTML = ''; + + if (!result || !result.translation) { + translationResultContainer.innerHTML = '
翻译失败,请尝试重新翻译
'; + return; + } + + // 创建结果容器 + const resultDiv = document.createElement('div'); + resultDiv.className = 'translation-result'; + + // 检测到的源语言 + if (result.detected_language) { + const detectedLangDiv = document.createElement('div'); + detectedLangDiv.className = 'detected-language'; + detectedLangDiv.innerHTML = `检测到的语言:${result.detected_language}`; + resultDiv.appendChild(detectedLangDiv); + } + + // 主要翻译结果 + const mainTranslationDiv = document.createElement('div'); + mainTranslationDiv.className = 'main-translation'; + mainTranslationDiv.innerHTML = ` +
+ 翻译结果: + +
+
${result.translation}
+ `; + resultDiv.appendChild(mainTranslationDiv); + + // 发音指导 + if (result.pronunciation) { + const pronunciationDiv = document.createElement('div'); + pronunciationDiv.className = 'pronunciation'; + pronunciationDiv.innerHTML = `发音:${result.pronunciation}`; + resultDiv.appendChild(pronunciationDiv); + } + + // 备选翻译 + if (result.alternative_translations && result.alternative_translations.length > 0) { + const alternativesDiv = document.createElement('div'); + alternativesDiv.className = 'alternatives'; + alternativesDiv.innerHTML = '
备选翻译:
'; + + result.alternative_translations.forEach((alt, index) => { + if (alt && alt.trim()) { + const altDiv = document.createElement('div'); + altDiv.className = 'alternative-item'; + altDiv.innerHTML = ` + ${alt} + + `; + alternativesDiv.appendChild(altDiv); + } + }); + + resultDiv.appendChild(alternativesDiv); + } + + // 翻译说明 + if (result.explanation) { + const explanationDiv = document.createElement('div'); + explanationDiv.className = 'explanation'; + explanationDiv.innerHTML = `翻译说明:
${result.explanation}
`; + resultDiv.appendChild(explanationDiv); + } + + translationResultContainer.appendChild(resultDiv); +} + +// 复制到剪贴板 +function copyToClipboard(text) { + navigator.clipboard.writeText(text).then(() => { + showSuccessToast('已复制到剪贴板'); + }).catch(err => { + console.error('复制失败:', err); + // 备用复制方法 + const textArea = document.createElement('textarea'); + textArea.value = text; + document.body.appendChild(textArea); + textArea.select(); + try { + document.execCommand('copy'); + showSuccessToast('已复制到剪贴板'); + } catch (e) { + showErrorMessage('复制失败,请手动复制'); + } + document.body.removeChild(textArea); + }); +} + +// 显示成功提示 +function showSuccessToast(message) { + const toast = document.createElement('div'); + toast.className = 'success-toast'; + toast.textContent = message; + document.body.appendChild(toast); + + setTimeout(() => { + toast.classList.add('show'); + }, 100); + + setTimeout(() => { + toast.classList.remove('show'); + setTimeout(() => { + document.body.removeChild(toast); + }, 300); + }, 2000); +} + +// 显示错误信息 +function showErrorMessage(message) { + const errorDiv = document.createElement('div'); + errorDiv.className = 'error'; + errorDiv.textContent = message; + translationResultContainer.innerHTML = ''; + translationResultContainer.appendChild(errorDiv); +} + +// 显示加载状态 +function showLoading(show) { + loadingDiv.style.display = show ? 'block' : 'none'; + translateBtn.disabled = show; + translateBtn.textContent = show ? '翻译中...' : '开始翻译'; +} + +// 执行翻译 +async function performTranslation() { + const sourceText = sourceTextInput.value.trim(); + const targetLanguage = targetLanguageSelect.value; + + if (!sourceText) { + showErrorMessage('请输入要翻译的内容'); + return; + } + + showLoading(true); + translationResultContainer.innerHTML = ''; + + try { + const result = await callBackendAPI(sourceText, targetLanguage); + const parsedResult = parseAIResponse(result); + displayTranslationResult(parsedResult); + } catch (error) { + console.error('翻译失败:', error); + showErrorMessage(`翻译失败: ${error.message}`); + } finally { + showLoading(false); + } +} + +// 事件监听器 +translateBtn.addEventListener('click', performTranslation); + +// 回车键翻译 +sourceTextInput.addEventListener('keypress', (e) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + performTranslation(); + } +}); + +// 页面加载完成后的初始化 +document.addEventListener('DOMContentLoaded', () => { + // 设置默认占位符 + translationResultContainer.innerHTML = '
请输入要翻译的内容,然后选择目标语言并点击翻译按钮
'; +}); + +// 导出函数供HTML调用 +window.copyToClipboard = copyToClipboard; +window.performTranslation = performTranslation; \ No newline at end of file diff --git a/InfoGenie-frontend/public/aimodelapp/AI语言翻译助手/styles.css b/InfoGenie-frontend/public/aimodelapp/AI语言翻译助手/styles.css new file mode 100644 index 00000000..5e1806c2 --- /dev/null +++ b/InfoGenie-frontend/public/aimodelapp/AI语言翻译助手/styles.css @@ -0,0 +1,488 @@ +/* 全局样式重置 */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +/* 主体样式 - iOS风格 */ +body { + font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Helvetica Neue', Arial, sans-serif; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + min-height: 100vh; + padding: 20px; + color: #1D1D1F; + line-height: 1.47; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* 容器样式 - iOS毛玻璃效果 */ +.container { + max-width: 800px; + margin: 0 auto; + background: rgba(255, 255, 255, 0.85); + border-radius: 24px; + padding: 32px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.08); + backdrop-filter: blur(20px) saturate(180%); + border: 1px solid rgba(255, 255, 255, 0.2); +} + +/* 头部样式 - iOS风格 */ +.header { + text-align: center; + margin-bottom: 32px; +} + +.title { + font-size: 2.25rem; + color: #1D1D1F; + margin-bottom: 8px; + font-weight: 600; + letter-spacing: -0.02em; +} + +.subtitle { + color: #86868B; + font-size: 1.0625rem; + margin-bottom: 24px; + font-weight: 400; +} + +/* 表单样式 - iOS风格 */ +.form-section { + margin-bottom: 32px; +} + +.form-group { + margin-bottom: 24px; +} + +.form-label { + display: block; + margin-bottom: 8px; + font-weight: 600; + color: #1D1D1F; + font-size: 1rem; +} + +.form-input { + width: 100%; + padding: 16px; + border: 1px solid rgba(0, 0, 0, 0.1); + border-radius: 12px; + font-size: 1rem; + transition: all 0.2s ease; + background: rgba(255, 255, 255, 0.8); + font-family: inherit; + backdrop-filter: blur(10px); +} + +.form-input:focus { + outline: none; + border-color: #007AFF; + background: rgba(255, 255, 255, 0.95); + box-shadow: 0 0 0 4px rgba(0, 122, 255, 0.1); +} + +.textarea { + resize: vertical; + min-height: 120px; +} + +.select { + cursor: pointer; + appearance: none; + background-image: url('data:image/svg+xml;charset=US-ASCII,'); + background-repeat: no-repeat; + background-position: right 15px center; + background-size: 12px; + padding-right: 40px; +} + +/* 按钮样式 - iOS风格 */ +.btn { + width: 100%; + padding: 16px; + background: #007AFF; + color: white; + border: none; + border-radius: 12px; + font-size: 1.0625rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(0, 122, 255, 0.25); +} + +.btn:hover { + background: #0056CC; + transform: translateY(-1px); + box-shadow: 0 4px 16px rgba(0, 122, 255, 0.35); +} + +.btn:active { + transform: translateY(0); + background: #004499; +} + +.btn:disabled { + opacity: 0.5; + cursor: not-allowed; + transform: none; + background: #86868B; +} + +/* 结果区域样式 - iOS风格 */ +.result-section { + margin-top: 32px; +} + +.result-title { + font-size: 1.25rem; + color: #1D1D1F; + margin-bottom: 16px; + text-align: center; + font-weight: 600; +} + +.loading { + display: none; + text-align: center; + color: #007AFF; + font-style: normal; + padding: 24px; + font-weight: 500; +} + +.translation-container { + background: rgba(255, 255, 255, 0.6); + border: 1px solid rgba(0, 0, 0, 0.08); + border-radius: 16px; + padding: 24px; + min-height: 150px; + backdrop-filter: blur(10px); +} + +.placeholder { + text-align: center; + color: #86868B; + font-style: normal; + padding: 40px 20px; + font-weight: 400; +} + +/* 翻译结果样式 */ +.translation-result { + animation: fadeIn 0.3s ease; +} + +.detected-language { + background: rgba(52, 199, 89, 0.1); + border: 1px solid rgba(52, 199, 89, 0.2); + border-radius: 12px; + padding: 12px 16px; + margin-bottom: 16px; + font-size: 0.9375rem; +} + +.detected-language .label { + font-weight: 600; + color: #34C759; + margin-right: 8px; +} + +.detected-language .value { + color: #1D1D1F; +} + +.main-translation { + background: rgba(255, 255, 255, 0.9); + border: 1px solid rgba(0, 0, 0, 0.06); + border-radius: 12px; + padding: 20px; + margin-bottom: 16px; + position: relative; +} + +.translation-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 12px; +} + +.translation-header .label { + font-weight: 600; + color: #1D1D1F; + font-size: 1rem; +} + +.translation-text { + font-size: 1.125rem; + color: #1D1D1F; + line-height: 1.6; + font-weight: 500; +} + +.pronunciation { + background: rgba(255, 149, 0, 0.1); + border: 1px solid rgba(255, 149, 0, 0.2); + border-radius: 12px; + padding: 12px 16px; + margin-bottom: 16px; + font-size: 0.9375rem; +} + +.pronunciation .label { + font-weight: 600; + color: #FF9500; + margin-right: 8px; +} + +.pronunciation .value { + color: #1D1D1F; + font-family: 'SF Mono', 'Monaco', 'Consolas', 'Courier New', monospace; +} + +.alternatives { + background: rgba(255, 255, 255, 0.8); + border: 1px solid rgba(0, 0, 0, 0.06); + border-radius: 12px; + padding: 16px; + margin-bottom: 16px; +} + +.alternatives-title { + font-weight: 600; + color: #1D1D1F; + margin-bottom: 12px; + font-size: 1rem; +} + +.alternative-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 12px; + margin-bottom: 8px; + background: rgba(255, 255, 255, 0.6); + border-radius: 8px; + transition: all 0.2s ease; +} + +.alternative-item:hover { + background: rgba(255, 255, 255, 0.9); +} + +.alternative-item:last-child { + margin-bottom: 0; +} + +.alternative-text { + color: #1D1D1F; + font-size: 1rem; +} + +.explanation { + background: rgba(0, 122, 255, 0.1); + border: 1px solid rgba(0, 122, 255, 0.2); + border-radius: 12px; + padding: 16px; +} + +.explanation .label { + font-weight: 600; + color: #007AFF; + margin-bottom: 8px; + display: block; +} + +.explanation-text { + color: #1D1D1F; + line-height: 1.6; + font-size: 0.9375rem; +} + +/* 复制按钮样式 */ +.copy-btn { + background: #007AFF; + color: white; + border: none; + border-radius: 8px; + padding: 8px 16px; + font-size: 0.8125rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: 0 2px 4px rgba(0, 122, 255, 0.25); +} + +.copy-btn:hover { + background: #0056CC; + transform: translateY(-1px); +} + +.copy-btn-small { + background: #007AFF; + color: white; + border: none; + border-radius: 6px; + padding: 4px 8px; + font-size: 0.75rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: 0 1px 2px rgba(0, 122, 255, 0.25); +} + +.copy-btn-small:hover { + background: #0056CC; + transform: translateY(-1px); +} + +/* 错误样式 - iOS风格 */ +.error { + color: #FF3B30; + background: rgba(255, 59, 48, 0.1); + border: 1px solid rgba(255, 59, 48, 0.2); + padding: 16px; + border-radius: 12px; + margin-top: 16px; + font-weight: 500; + backdrop-filter: blur(10px); +} + +/* 成功提示 - iOS风格 */ +.success-toast { + position: fixed; + top: 20px; + right: 20px; + background: #34C759; + color: white; + padding: 12px 20px; + border-radius: 12px; + box-shadow: 0 8px 24px rgba(52, 199, 89, 0.3); + z-index: 1000; + opacity: 0; + transform: translateX(100%); + transition: all 0.3s ease; + font-weight: 600; + backdrop-filter: blur(20px); +} + +.success-toast.show { + opacity: 1; + transform: translateX(0); +} + +/* 响应式设计 */ +@media (max-width: 768px) { + body { + padding: 10px; + } + + .container { + padding: 20px; + margin: 10px; + } + + .title { + font-size: 2rem; + } + + .form-input { + padding: 12px; + } + + .btn { + padding: 12px; + } + + .translation-container { + padding: 15px; + } + + .main-translation { + padding: 15px; + } + + .translation-header { + flex-direction: column; + align-items: flex-start; + gap: 8px; + } + + .copy-btn { + align-self: flex-end; + } + + .alternative-item { + flex-direction: column; + align-items: flex-start; + gap: 8px; + } + + .copy-btn-small { + align-self: flex-end; + } +} + +@media (max-width: 480px) { + .title { + font-size: 1.8rem; + letter-spacing: 1px; + } + + .container { + padding: 15px; + } + + .form-input { + padding: 10px; + } + + .main-translation { + padding: 12px; + } + + .translation-text { + font-size: 1rem; + } + + .alternative-text { + font-size: 0.9375rem; + } +} + +/* 动画效果 */ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.translation-result { + animation: fadeIn 0.3s ease; +} + +/* 加载动画 */ +@keyframes pulse { + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } +} + +.loading { + animation: pulse 1.5s ease-in-out infinite; +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/aimodelapp/API测试页面.html b/InfoGenie-frontend/public/aimodelapp/API测试页面.html new file mode 100644 index 00000000..19ff3b18 --- /dev/null +++ b/InfoGenie-frontend/public/aimodelapp/API测试页面.html @@ -0,0 +1,228 @@ + + + + + + API超时修复测试 + + + +
+

🔧 API超时修复测试

+ +
+

🎭 表情制作器API测试

+ + + +
+
+ +
+

📝 变量命名API测试

+ + +
+
+
+ + + + \ No newline at end of file diff --git a/frontend/public/aimodelapp/生成要求.txt b/InfoGenie-frontend/public/aimodelapp/生成要求.txt old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/aimodelapp/生成要求.txt rename to InfoGenie-frontend/public/aimodelapp/生成要求.txt diff --git a/InfoGenie-frontend/public/assets/logo.png b/InfoGenie-frontend/public/assets/logo.png new file mode 100644 index 00000000..4c81f1ac Binary files /dev/null and b/InfoGenie-frontend/public/assets/logo.png differ diff --git a/frontend/public/index.html b/InfoGenie-frontend/public/index.html old mode 100755 new mode 100644 similarity index 89% rename from frontend/public/index.html rename to InfoGenie-frontend/public/index.html index bd22830c..dfaaec1b --- a/frontend/public/index.html +++ b/InfoGenie-frontend/public/index.html @@ -19,10 +19,10 @@ - + - + @@ -41,7 +41,7 @@ left: 0; width: 100%; height: 100%; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + background: linear-gradient(135deg, #90EE90 0%, #F0E68C 100%); display: flex; flex-direction: column; align-items: center; @@ -52,9 +52,11 @@ } #loading .loading-logo { - font-size: 64px; + width: 64px; + height: 64px; margin-bottom: 24px; animation: pulse 2s infinite; + border-radius: 8px; } #loading .loading-text { @@ -89,7 +91,7 @@ } @media (max-width: 768px) { - #loading .loading-logo { font-size: 48px; } + #loading .loading-logo { width: 48px; height: 48px; } #loading .loading-text { font-size: 20px; } } @@ -99,7 +101,7 @@
- +
神奇万事通
🎨 多功能聚合应用 💬
diff --git a/frontend/public/manifest.json b/InfoGenie-frontend/public/manifest.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/manifest.json rename to InfoGenie-frontend/public/manifest.json diff --git a/frontend/public/smallgame/2048/controls.js b/InfoGenie-frontend/public/smallgame/2048/controls.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/smallgame/2048/controls.js rename to InfoGenie-frontend/public/smallgame/2048/controls.js diff --git a/frontend/public/smallgame/2048/game-logic.js b/InfoGenie-frontend/public/smallgame/2048/game-logic.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/smallgame/2048/game-logic.js rename to InfoGenie-frontend/public/smallgame/2048/game-logic.js diff --git a/frontend/public/smallgame/2048/index.html b/InfoGenie-frontend/public/smallgame/2048/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/smallgame/2048/index.html rename to InfoGenie-frontend/public/smallgame/2048/index.html diff --git a/frontend/public/smallgame/2048/statistics.js b/InfoGenie-frontend/public/smallgame/2048/statistics.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/smallgame/2048/statistics.js rename to InfoGenie-frontend/public/smallgame/2048/statistics.js diff --git a/frontend/public/smallgame/2048/styles.css b/InfoGenie-frontend/public/smallgame/2048/styles.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/smallgame/2048/styles.css rename to InfoGenie-frontend/public/smallgame/2048/styles.css diff --git a/frontend/public/smallgame/俄罗斯方块/game-controls.js b/InfoGenie-frontend/public/smallgame/俄罗斯方块/game-controls.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/smallgame/俄罗斯方块/game-controls.js rename to InfoGenie-frontend/public/smallgame/俄罗斯方块/game-controls.js diff --git a/frontend/public/smallgame/俄罗斯方块/game-stats.js b/InfoGenie-frontend/public/smallgame/俄罗斯方块/game-stats.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/smallgame/俄罗斯方块/game-stats.js rename to InfoGenie-frontend/public/smallgame/俄罗斯方块/game-stats.js diff --git a/frontend/public/smallgame/俄罗斯方块/index.html b/InfoGenie-frontend/public/smallgame/俄罗斯方块/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/smallgame/俄罗斯方块/index.html rename to InfoGenie-frontend/public/smallgame/俄罗斯方块/index.html diff --git a/frontend/public/smallgame/俄罗斯方块/styles.css b/InfoGenie-frontend/public/smallgame/俄罗斯方块/styles.css old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/smallgame/俄罗斯方块/styles.css rename to InfoGenie-frontend/public/smallgame/俄罗斯方块/styles.css diff --git a/frontend/public/smallgame/俄罗斯方块/tetris.js b/InfoGenie-frontend/public/smallgame/俄罗斯方块/tetris.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/smallgame/俄罗斯方块/tetris.js rename to InfoGenie-frontend/public/smallgame/俄罗斯方块/tetris.js diff --git a/frontend/public/smallgame/别踩白方块/MUSIC.mp3 b/InfoGenie-frontend/public/smallgame/别踩白方块/MUSIC.mp3 old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/smallgame/别踩白方块/MUSIC.mp3 rename to InfoGenie-frontend/public/smallgame/别踩白方块/MUSIC.mp3 diff --git a/frontend/public/smallgame/别踩白方块/game.js b/InfoGenie-frontend/public/smallgame/别踩白方块/game.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/smallgame/别踩白方块/game.js rename to InfoGenie-frontend/public/smallgame/别踩白方块/game.js diff --git a/frontend/public/smallgame/别踩白方块/index.html b/InfoGenie-frontend/public/smallgame/别踩白方块/index.html old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/smallgame/别踩白方块/index.html rename to InfoGenie-frontend/public/smallgame/别踩白方块/index.html diff --git a/InfoGenie-frontend/public/smallgame/扫雷/css/style.css b/InfoGenie-frontend/public/smallgame/扫雷/css/style.css new file mode 100644 index 00000000..28b2da6a --- /dev/null +++ b/InfoGenie-frontend/public/smallgame/扫雷/css/style.css @@ -0,0 +1,79 @@ +/* 经典扫雷 - 手机竖屏优先 + 电脑端适配 */ +:root{ + --bg:#0f172a; + --panel:#111827; + --accent:#22d3ee; + --accent-2:#60a5fa; + --text:#e5e7eb; + --muted:#94a3b8; + --danger:#ef4444; + --success:#22c55e; + --warn:#f59e0b; + --cell:#1f2937; + --cell-hover:#273244; + --flag:#fb7185; +} +*{box-sizing:border-box} +html,body{height:100%;} +body{margin:0;background:linear-gradient(180deg,#0b1220,#0f172a);color:var(--text);font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,"PingFang SC","Microsoft Yahei",sans-serif;-webkit-tap-highlight-color:transparent} + +.app{min-height:100dvh;display:flex;flex-direction:column;gap:12px;padding:12px;} +.header{display:flex;flex-direction:column;gap:10px;background:rgba(255,255,255,0.02);border:1px solid rgba(255,255,255,0.06);border-radius:14px;padding:12px 12px 10px;backdrop-filter:blur(6px)} +.title{margin:0;font-size:20px;letter-spacing:1px} +.hud{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;align-items:center} +.hud-item{display:flex;flex-direction:column;align-items:center;justify-content:center;background:var(--panel);border:1px solid rgba(255,255,255,0.06);border-radius:10px;padding:8px 6px} +.hud-item .label{font-size:12px;color:var(--muted)} +.hud-item .value{font-size:18px;font-weight:700;color:#fff} +.btn{appearance:none;border:none;background:#1e293b;color:#fff;padding:10px 12px;border-radius:10px;cursor:pointer;outline:none;transition:.15s transform,.15s background;display:inline-flex;align-items:center;justify-content:center} +.btn:active{transform:scale(.98)} +.btn.primary{background:linear-gradient(90deg,var(--accent),var(--accent-2))} +.btn.primary:active{filter:brightness(.95)} + +.main{display:flex;flex-direction:column;gap:12px} +.board-wrapper{display:flex;justify-content:center;align-items:center} +.board{display:grid;gap:4px;touch-action:manipulation;user-select:none;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06);border-radius:12px;padding:6px;width:100%;max-width:92vw} +.cell{display:grid;place-items:center;background:var(--cell);border-radius:8px;border:1px solid rgba(255,255,255,0.06);font-weight:700;color:#9ca3af;box-shadow:inset 0 -1px 0 rgba(255,255,255,0.04);aspect-ratio:1/1;font-size:clamp(12px, 2.2vw, 18px)} +.cell.revealed{background:#0b1220;color:#e5e7eb} +.cell:hover{background:var(--cell-hover)} +.cell.flag::after{content:"🚩"} +.cell.mine.revealed{background:#3b0d0d;color:#fff} +.cell.mine.revealed::after{content:"💣"} +.cell[data-n="1"].revealed{color:#60a5fa} +.cell[data-n="2"].revealed{color:#34d399} +.cell[data-n="3"].revealed{color:#f87171} +.cell[data-n="4"].revealed{color:#a78bfa} +.cell[data-n="5"].revealed{color:#fbbf24} +.cell[data-n="6"].revealed{color:#22d3ee} +.cell[data-n="7"].revealed{color:#e879f9} +.cell[data-n="8"].revealed{color:#cbd5e1} + +.tips{font-size:12px;color:var(--muted);text-align:center} +.toast{position:fixed;left:50%;bottom:18px;transform:translateX(-50%);background:rgba(17,24,39,.95);border:1px solid rgba(255,255,255,.08);padding:10px 14px;border-radius:10px} + +.modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.45);display:grid;place-items:center;padding:14px} +.modal{width:min(520px,92vw);background:linear-gradient(180deg,#0f172a,#0b1320);border:1px solid rgba(255,255,255,0.08);border-radius:14px;padding:16px 14px} +.modal h2{margin:4px 0 8px;font-size:20px} +.stats{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin:8px 0 14px} +.stats .card{background:var(--panel);border:1px solid rgba(255,255,255,0.06);border-radius:10px;padding:10px} +.stats .card .k{font-size:12px;color:var(--muted)} +.stats .card .v{font-size:18px;font-weight:700} +.modal-actions{display:flex;gap:10px;justify-content:flex-end} + +/* 响应式:手机竖屏优先 */ +@media (min-width: 480px){ + .title{font-size:22px} +} +@media (min-width: 640px){ + .app{padding:18px} + .hud{grid-template-columns:repeat(5,minmax(0,1fr))} +} +@media (min-width: 1024px){ + .board{ max-width: 420px; } + .header{ padding:10px 10px 8px; } + .hud-item{ padding:6px 4px; } + .hud-item .value{ font-size:16px; } + .title{ font-size:18px; } +} +@media (orientation: landscape) and (max-width: 900px){ + .board{transform:scale(.9)} +} \ No newline at end of file diff --git a/InfoGenie-frontend/public/smallgame/扫雷/index.html b/InfoGenie-frontend/public/smallgame/扫雷/index.html new file mode 100644 index 00000000..57865d5f --- /dev/null +++ b/InfoGenie-frontend/public/smallgame/扫雷/index.html @@ -0,0 +1,56 @@ + + + + + + + + 经典扫雷(手机竖屏适配) + + + + + + +
+
+

经典扫雷

+
+
关卡1
+
雷数0
+
计时00:00
+ +
+
+ +
+
+
+
+ +
+

+ 手机:点开格子,长按插旗;电脑:左键开格,右键插旗;键盘:方向键移动,空格/回车开格,F 插旗。 +

+
+
+ + + + + + +
+ + + + \ No newline at end of file diff --git a/InfoGenie-frontend/public/smallgame/扫雷/js/main.js b/InfoGenie-frontend/public/smallgame/扫雷/js/main.js new file mode 100644 index 00000000..6c78e3c6 --- /dev/null +++ b/InfoGenie-frontend/public/smallgame/扫雷/js/main.js @@ -0,0 +1,273 @@ +// 经典扫雷(手机竖屏适配 + 无尽模式 + 键盘操作) +// 模块:状态、生成、交互、键盘、统计 + +class RNG { + constructor(seed = Date.now()) { this.seed = seed >>> 0; } + next() { // xorshift32 + let x = this.seed; + x ^= x << 13; x ^= x >>> 17; x ^= x << 5; + this.seed = x >>> 0; return this.seed / 0xffffffff; + } + range(min, max){ return Math.floor(this.next() * (max - min + 1)) + min; } +} + +const GameConfig = { + start: { rows: 10, cols: 8, mineRatio: 0.12 }, // 竖屏优先:更多行 + levelStep(cfg){ + // 难度递增:逐步增加行列与雷密度,控制在移动端也能点击 + const next = { ...cfg }; + if (next.rows < 16) next.rows++; + if (next.cols < 12) next.cols += (next.rows % 2 === 0 ? 1 : 0); + next.mineRatio = Math.min(0.24, +(next.mineRatio + 0.02).toFixed(2)); + return next; + } +} + +const State = { + level: 1, + rows: 0, + cols: 0, + mineCount: 0, + revealed: 0, + flags: 0, + grid: [], // { mine, r, c, around, revealed, flag } + timer: 0, + timerId: null, + startTs: 0, + rng: new RNG(), + stats: { opened:0, flagged:0, mistakes:0, time:0 } +}; + +function el(sel){ return document.querySelector(sel); } +function make(tag, cls){ const e = document.createElement(tag); if(cls) e.className = cls; return e; } +function updateMinesHud(){ el('#mines').textContent = String(Math.max(0, State.mineCount - State.flags)); } + +function startTimer(){ + State.startTs = Date.now(); + const timerEl = el('#timer'); + clearInterval(State.timerId); + State.timerId = setInterval(() => { + State.timer = Math.floor((Date.now() - State.startTs)/1000); + const m = String(Math.floor(State.timer/60)).padStart(2,'0'); + const s = String(State.timer%60).padStart(2,'0'); + timerEl.textContent = `${m}:${s}`; + }, 250); +} +function stopTimer(){ clearInterval(State.timerId); State.timerId = null; } + +function setupBoard(cfg){ + State.rows = cfg.rows; State.cols = cfg.cols; + const total = cfg.rows * cfg.cols; + State.mineCount = Math.max(1, Math.floor(total * cfg.mineRatio)); + State.revealed = 0; State.flags = 0; State.grid = []; + State.stats = { opened:0, flagged:0, mistakes:0, time:0 }; + + // 更新HUD + el('#level').textContent = String(State.level); + updateMinesHud(); + + const board = el('#board'); + board.innerHTML = ''; + board.style.gridTemplateColumns = `repeat(${State.cols}, 1fr)`; + + // 生成空格子 + for(let r=0;r e.preventDefault()); + // 触摸长按 + let pressTimer = null; let longPressed=false; + div.addEventListener('touchstart', e => { + longPressed=false; + pressTimer = setTimeout(()=>{ longPressed=true; toggleFlag(cell); }, 420); + }, {passive:true}); + div.addEventListener('touchend', e => { if(pressTimer){ clearTimeout(pressTimer); if(!longPressed) openCell(cell); } }); + // 鼠标 + div.addEventListener('mousedown', e => { + if(e.button===2){ toggleFlag(cell); } + else if(e.button===0){ if(cell.revealed && cell.around>0) chord(cell); else openCell(cell); } + }); + cell.el = div; + State.grid[r][c] = cell; + board.appendChild(div); + } + } + + // 随机埋雷 + let placed=0; + const setMine = (r,c)=>{ if(!State.grid[r][c].mine){ State.grid[r][c].mine=true; placed++; } }; + while(placed < State.mineCount){ setMine(State.rng.range(0,State.rows-1), State.rng.range(0,State.cols-1)); } + recomputeArounds(); + // 启动计时 + startTimer(); +} + +function visitNeighbors(r,c, cb){ + for(let dr=-1; dr<=1; dr++){ + for(let dc=-1; dc<=1; dc++){ + if(dr===0 && dc===0) continue; + const nr=r+dr, nc=c+dc; + if(nr>=0 && nr=0 && nc{ if(State.grid[nr][nc].flag) n++; }); return n; } +function chord(cell){ + if(!cell.revealed || cell.around<=0) return; + const flagged = countFlagsAround(cell.r, cell.c); + if(flagged === cell.around){ + visitNeighbors(cell.r, cell.c, (nr,nc)=>{ + const ncell = State.grid[nr][nc]; + if(!ncell.revealed && !ncell.flag){ openCell(ncell); } + }); + } +} +function recomputeArounds(){ + for(let r=0;r{ if(State.grid[nr][nc].mine) n++; }); + State.grid[r][c].around = n; + } + } +} +function safeFirstClick(badCell){ + // 移除当前雷并将其放到其他非雷位置 + badCell.mine = false; + while(true){ + const r = State.rng.range(0, State.rows-1); + const c = State.rng.range(0, State.cols-1); + const target = State.grid[r][c]; + if(target!==badCell && !target.mine){ target.mine = true; break; } + } + recomputeArounds(); +} + +function openCell(cell){ + if(cell.revealed || cell.flag) return; + // 首次点击必定安全:若第一次就点到雷,则移动该雷并重算数字 + if(State.revealed===0 && cell.mine){ + safeFirstClick(cell); + } + cell.revealed = true; State.revealed++; State.stats.opened++; + cell.el.classList.add('revealed'); + if(cell.mine){ + cell.el.classList.add('mine'); + endGame(false); + return; + } + if(cell.around>0){ cell.el.dataset.n = cell.around; cell.el.textContent = cell.around; } + else{ + // flood fill + visitNeighbors(cell.r, cell.c, (nr,nc)=>{ + const ncell = State.grid[nr][nc]; + if(!ncell.revealed && !ncell.mine) openCell(ncell); + }); + } + checkWin(); +} + +function toggleFlag(cell){ + if(cell.revealed) return; + cell.flag = !cell.flag; + State.flags += cell.flag ? 1 : -1; + State.stats.flagged += cell.flag ? 1 : 0; + cell.el.classList.toggle('flag', cell.flag); + updateMinesHud(); +} + +function checkWin(){ + const totalSafe = State.rows*State.cols - State.mineCount; + if(State.revealed >= totalSafe){ + // 通关 -> 进入下一关 + showToast(`第 ${State.level} 关完成!`); + stopTimer(); + setTimeout(()=>{ + State.level++; + const nextCfg = GameConfig.levelStep({ rows: State.rows, cols: State.cols, mineRatio: State.mineCount/(State.rows*State.cols) }); + setupBoard(nextCfg); + }, 600); + } +} + +function showToast(msg){ + const t = el('#toast-level'); + t.textContent = msg; t.style.display='block'; + t.animate([ + { transform:'translate(-50%, 20px)', opacity:0 }, + { transform:'translate(-50%, 0)', opacity:1, offset:.2 }, + { transform:'translate(-50%, 0)', opacity:1, offset:.8 }, + { transform:'translate(-50%, 10px)', opacity:0 } + ], { duration:1200, easing:'ease' }).onfinish = ()=> t.style.display='none'; +} + +function endGame(win){ + stopTimer(); + // 展示所有雷 + for(let r=0;r +
关卡
${State.level}
+
总用时
${formatTime(State.timer)}
+
开格
${State.stats.opened}
+
插旗
${State.stats.flagged}
+
+

再接再厉,挑战更高难度!

+ `; + el('#stats').innerHTML = statsHtml; + el('#modal-overlay').style.display = 'grid'; +} + +function formatTime(sec){ const m=Math.floor(sec/60), s=sec%60; return `${String(m).padStart(2,'0')}:${String(s).padStart(2,'0')}`; } + +function bindUI(){ + el('#btn-restart').addEventListener('click', ()=> restart()); + el('#btn-retry').addEventListener('click', ()=> restart()); + el('#btn-close').addEventListener('click', ()=>{ el('#modal-overlay').style.display='none'; }); +} + +function restart(){ + el('#modal-overlay').style.display='none'; + State.level = 1; setupBoard(GameConfig.start); +} + +// 键盘操作(电脑端) +let kb = { r:0, c:0 }; +function bindKeyboard(){ + document.addEventListener('keydown', (e)=>{ + const key = e.key.toLowerCase(); + if(['arrowup','w'].includes(key)) move(-1,0); + else if(['arrowdown','s'].includes(key)) move(1,0); + else if(['arrowleft','a'].includes(key)) move(0,-1); + else if(['arrowright','d'].includes(key)) move(0,1); + else if(key==='f'){ toggleFlag(State.grid[kb.r][kb.c]); highlightFocus(); } + else if(key===' ' || key==='enter'){ openCell(State.grid[kb.r][kb.c]); highlightFocus(); } + }); +} +function move(dr,dc){ kb.r = clamp(kb.r+dr,0,State.rows-1); kb.c = clamp(kb.c+dc,0,State.cols-1); highlightFocus(); } +function clamp(v,min,max){ return Math.max(min, Math.min(max, v)); } +function highlightFocus(){ + // 简单高亮当前聚焦格 + for(let r=0;r { + this.game.changeDirection(0, -1); + }); + + document.getElementById('downBtn').addEventListener('click', () => { + this.game.changeDirection(0, 1); + }); + + document.getElementById('leftBtn').addEventListener('click', () => { + this.game.changeDirection(-1, 0); + }); + + document.getElementById('rightBtn').addEventListener('click', () => { + this.game.changeDirection(1, 0); + }); + + // 暂停/继续按钮 + document.getElementById('pauseBtn').addEventListener('click', () => { + this.game.togglePause(); + }); + + // 重新开始按钮 + document.getElementById('restartBtn').addEventListener('click', () => { + this.game.restart(); + }); + + // 键盘快捷键 + this.initKeyboardShortcuts(); + } + + initKeyboardShortcuts() { + document.addEventListener('keydown', (e) => { + switch(e.key) { + case 'r': + case 'R': + if (this.game.gameOver) { + this.game.restart(); + } + break; + case 'p': + case 'P': + this.game.togglePause(); + break; + case 'Escape': + if (this.game.gameOver) { + document.getElementById('gameOverModal').style.display = 'none'; + } + break; + } + }); + } + + initTouchControls() { + const canvas = document.getElementById('gameCanvas'); + let touchStartX = 0; + let touchStartY = 0; + + canvas.addEventListener('touchstart', (e) => { + touchStartX = e.touches[0].clientX; + touchStartY = e.touches[0].clientY; + e.preventDefault(); + }, { passive: false }); + + canvas.addEventListener('touchmove', (e) => { + e.preventDefault(); + }, { passive: false }); + + canvas.addEventListener('touchend', (e) => { + const touchEndX = e.changedTouches[0].clientX; + const touchEndY = e.changedTouches[0].clientY; + + const deltaX = touchEndX - touchStartX; + const deltaY = touchEndY - touchStartY; + const minSwipeDistance = 30; + + if (Math.abs(deltaX) > Math.abs(deltaY)) { + // 水平滑动 + if (Math.abs(deltaX) > minSwipeDistance) { + if (deltaX > 0) { + this.game.changeDirection(1, 0); // 右滑 + } else { + this.game.changeDirection(-1, 0); // 左滑 + } + } + } else { + // 垂直滑动 + if (Math.abs(deltaY) > minSwipeDistance) { + if (deltaY > 0) { + this.game.changeDirection(0, 1); // 下滑 + } else { + this.game.changeDirection(0, -1); // 上滑 + } + } + } + + e.preventDefault(); + }, { passive: false }); + + // 防止移动端页面滚动 + document.addEventListener('touchmove', (e) => { + if (e.target.closest('.game-container')) { + e.preventDefault(); + } + }, { passive: false }); + } + + // 震动反馈(移动端) + vibrate(duration = 50) { + if ('vibrate' in navigator) { + navigator.vibrate(duration); + } + } +} + +// 初始化控制模块 +document.addEventListener('DOMContentLoaded', () => { + // 等待游戏实例创建后初始化控制 + setTimeout(() => { + new GameControls(game); + }, 100); +}); \ No newline at end of file diff --git a/InfoGenie-frontend/public/smallgame/贪吃蛇/game-core.js b/InfoGenie-frontend/public/smallgame/贪吃蛇/game-core.js new file mode 100644 index 00000000..46b5c8c1 --- /dev/null +++ b/InfoGenie-frontend/public/smallgame/贪吃蛇/game-core.js @@ -0,0 +1,366 @@ +class SnakeGame { + constructor() { + this.canvas = document.getElementById('gameCanvas'); + this.ctx = this.canvas.getContext('2d'); + + // 游戏配置 + this.gridSize = 20; + this.tileCount = this.canvas.width / this.gridSize; + this.tileCountY = this.canvas.height / this.gridSize; + + // 蛇的初始状态 + this.snake = [ + {x: 10, y: 10}, + {x: 9, y: 10}, + {x: 8, y: 10} + ]; + + // 食物位置 + this.food = {x: 15, y: 15}; + + // 游戏状态 + this.dx = 1; // 初始向右移动 + this.dy = 0; + this.score = 0; + this.level = 1; + this.gameSpeed = 10; // 初始速度 + this.isPaused = false; + this.gameOver = false; + this.startTime = Date.now(); + this.foodEaten = 0; + + // 特殊食物 + this.specialFood = null; + this.specialFoodTimer = 0; + this.specialFoodDuration = 5000; // 5秒 + + this.init(); + } + + init() { + this.generateFood(); + this.gameLoop(); + + // 监听键盘事件 + document.addEventListener('keydown', (e) => { + if (this.isPaused || this.gameOver) return; + + switch(e.key) { + case 'ArrowUp': + case 'w': + case 'W': + if (this.dy === 0) { + this.dx = 0; + this.dy = -1; + } + break; + case 'ArrowDown': + case 's': + case 'S': + if (this.dy === 0) { + this.dx = 0; + this.dy = 1; + } + break; + case 'ArrowLeft': + case 'a': + case 'A': + if (this.dx === 0) { + this.dx = -1; + this.dy = 0; + } + break; + case 'ArrowRight': + case 'd': + case 'D': + if (this.dx === 0) { + this.dx = 1; + this.dy = 0; + } + break; + case ' ': + this.togglePause(); + break; + } + }); + } + + generateFood() { + // 生成普通食物 + let newFood; + do { + newFood = { + x: Math.floor(Math.random() * this.tileCount), + y: Math.floor(Math.random() * this.tileCountY) + }; + } while (this.isPositionOccupied(newFood)); + + this.food = newFood; + + // 有10%几率生成特殊食物 + if (Math.random() < 0.1 && !this.specialFood) { + this.generateSpecialFood(); + } + } + + generateSpecialFood() { + let newFood; + do { + newFood = { + x: Math.floor(Math.random() * this.tileCount), + y: Math.floor(Math.random() * this.tileCountY), + type: 'special', + value: 5 // 特殊食物价值5分 + }; + } while (this.isPositionOccupied(newFood)); + + this.specialFood = newFood; + this.specialFoodTimer = Date.now(); + } + + isPositionOccupied(position) { + // 检查是否与蛇身重叠 + for (let segment of this.snake) { + if (segment.x === position.x && segment.y === position.y) { + return true; + } + } + + // 检查是否与普通食物重叠 + if (this.food && this.food.x === position.x && this.food.y === position.y) { + return true; + } + + // 检查是否与特殊食物重叠 + if (this.specialFood && this.specialFood.x === position.x && this.specialFood.y === position.y) { + return true; + } + + return false; + } + + update() { + if (this.isPaused || this.gameOver) return; + + // 更新蛇头位置 + const head = {x: this.snake[0].x + this.dx, y: this.snake[0].y + this.dy}; + + // 检查游戏结束条件 + if (this.checkCollision(head)) { + this.gameOver = true; + this.showGameOver(); + return; + } + + // 移动蛇 + this.snake.unshift(head); + + // 检查是否吃到食物 + if (head.x === this.food.x && head.y === this.food.y) { + this.score += 1; + this.foodEaten++; + this.generateFood(); + this.updateLevel(); + } else if (this.specialFood && head.x === this.specialFood.x && head.y === this.specialFood.y) { + this.score += this.specialFood.value; + this.foodEaten++; + this.specialFood = null; + this.generateFood(); + this.updateLevel(); + } else { + this.snake.pop(); // 如果没有吃到食物,移除尾部 + } + + // 检查特殊食物超时 + if (this.specialFood && Date.now() - this.specialFoodTimer > this.specialFoodDuration) { + this.specialFood = null; + } + + // 更新UI + this.updateUI(); + } + + checkCollision(head) { + // 检查撞墙 + if (head.x < 0 || head.x >= this.tileCount || head.y < 0 || head.y >= this.tileCountY) { + return true; + } + + // 检查撞到自己(从第4节开始检查,避免误判) + for (let i = 4; i < this.snake.length; i++) { + if (this.snake[i].x === head.x && this.snake[i].y === head.y) { + return true; + } + } + + return false; + } + + updateLevel() { + // 每吃5个食物升一级 + const newLevel = Math.floor(this.foodEaten / 5) + 1; + if (newLevel > this.level) { + this.level = newLevel; + this.gameSpeed = Math.min(20, 10 + this.level); // 速度上限20 + } + } + + updateUI() { + document.getElementById('score').textContent = this.score; + document.getElementById('length').textContent = this.snake.length; + document.getElementById('level').textContent = this.level; + } + + draw() { + // 清空画布 + this.ctx.fillStyle = '#222'; + this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); + + // 绘制网格(背景) + this.ctx.strokeStyle = '#333'; + this.ctx.lineWidth = 0.5; + for (let x = 0; x < this.tileCount; x++) { + for (let y = 0; y < this.tileCountY; y++) { + this.ctx.strokeRect(x * this.gridSize, y * this.gridSize, this.gridSize, this.gridSize); + } + } + + // 绘制蛇 + this.snake.forEach((segment, index) => { + if (index === 0) { + // 蛇头 + this.ctx.fillStyle = '#4CAF50'; + } else { + // 蛇身,渐变颜色 + const gradient = (index / this.snake.length) * 100; + this.ctx.fillStyle = `hsl(120, 80%, ${60 - gradient}%)`; + } + this.ctx.fillRect(segment.x * this.gridSize, segment.y * this.gridSize, this.gridSize, this.gridSize); + + // 边框 + this.ctx.strokeStyle = '#2E7D32'; + this.ctx.strokeRect(segment.x * this.gridSize, segment.y * this.gridSize, this.gridSize, this.gridSize); + }); + + // 绘制普通食物 + this.ctx.fillStyle = '#FF5252'; + this.ctx.beginPath(); + this.ctx.arc( + this.food.x * this.gridSize + this.gridSize / 2, + this.food.y * this.gridSize + this.gridSize / 2, + this.gridSize / 2 - 2, + 0, + Math.PI * 2 + ); + this.ctx.fill(); + + // 绘制特殊食物(如果存在) + if (this.specialFood) { + this.ctx.fillStyle = '#FFD700'; + this.ctx.beginPath(); + this.ctx.arc( + this.specialFood.x * this.gridSize + this.gridSize / 2, + this.specialFood.y * this.gridSize + this.gridSize / 2, + this.gridSize / 2 - 1, + 0, + Math.PI * 2 + ); + this.ctx.fill(); + + // 闪烁效果 + const time = Date.now() - this.specialFoodTimer; + const alpha = 0.5 + 0.5 * Math.sin(time / 200); + this.ctx.globalAlpha = alpha; + this.ctx.fillStyle = '#FF6B00'; + this.ctx.fill(); + this.ctx.globalAlpha = 1; + } + + // 绘制暂停状态 + if (this.isPaused) { + this.ctx.fillStyle = 'rgba(0, 0, 0, 0.7)'; + this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); + + this.ctx.fillStyle = 'white'; + this.ctx.font = '24px Arial'; + this.ctx.textAlign = 'center'; + this.ctx.fillText('游戏暂停', this.canvas.width / 2, this.canvas.height / 2); + } + } + + gameLoop() { + this.update(); + this.draw(); + + if (!this.gameOver) { + setTimeout(() => this.gameLoop(), 1000 / this.gameSpeed); + } + } + + togglePause() { + this.isPaused = !this.isPaused; + document.getElementById('pauseBtn').textContent = this.isPaused ? '继续' : '暂停'; + + if (!this.isPaused && !this.gameOver) { + this.gameLoop(); + } + } + + changeDirection(dx, dy) { + if (this.isPaused || this.gameOver) return; + + // 防止180度转弯 + if ((this.dx !== 0 && dx !== 0) || (this.dy !== 0 && dy !== 0)) { + return; + } + + this.dx = dx; + this.dy = dy; + } + + showGameOver() { + const modal = document.getElementById('gameOverModal'); + const gameTime = Math.floor((Date.now() - this.startTime) / 1000); + + document.getElementById('finalScore').textContent = this.score; + document.getElementById('finalLength').textContent = this.snake.length; + document.getElementById('finalLevel').textContent = this.level; + document.getElementById('gameTime').textContent = gameTime; + document.getElementById('foodEaten').textContent = this.foodEaten; + + modal.style.display = 'flex'; + } + + restart() { + this.snake = [ + {x: 10, y: 10}, + {x: 9, y: 10}, + {x: 8, y: 10} + ]; + this.dx = 1; + this.dy = 0; + this.score = 0; + this.level = 1; + this.gameSpeed = 10; + this.isPaused = false; + this.gameOver = false; + this.startTime = Date.now(); + this.foodEaten = 0; + this.specialFood = null; + + this.generateFood(); + this.updateUI(); + + document.getElementById('gameOverModal').style.display = 'none'; + document.getElementById('pauseBtn').textContent = '暂停'; + + this.gameLoop(); + } +} + +// 全局游戏实例 +let game; + +document.addEventListener('DOMContentLoaded', () => { + game = new SnakeGame(); +}); \ No newline at end of file diff --git a/InfoGenie-frontend/public/smallgame/贪吃蛇/game-stats.js b/InfoGenie-frontend/public/smallgame/贪吃蛇/game-stats.js new file mode 100644 index 00000000..2df9484d --- /dev/null +++ b/InfoGenie-frontend/public/smallgame/贪吃蛇/game-stats.js @@ -0,0 +1,295 @@ +class GameStatistics { + constructor() { + this.highScores = JSON.parse(localStorage.getItem('snakeHighScores')) || []; + this.sessionStats = { + gamesPlayed: 0, + totalScore: 0, + maxLength: 0, + maxLevel: 0, + totalTime: 0 + }; + + this.init(); + } + + init() { + // 恢复会话统计(如果存在) + const savedSession = localStorage.getItem('snakeSessionStats'); + if (savedSession) { + this.sessionStats = JSON.parse(savedSession); + } + + // 监听游戏事件 + this.setupEventListeners(); + } + + setupEventListeners() { + // 监听自定义游戏事件 + document.addEventListener('gameOver', (e) => { + this.handleGameOver(e.detail); + }); + + document.addEventListener('foodEaten', (e) => { + this.handleFoodEaten(e.detail); + }); + + document.addEventListener('levelUp', (e) => { + this.handleLevelUp(e.detail); + }); + } + + handleGameOver(gameData) { + this.sessionStats.gamesPlayed++; + this.sessionStats.totalScore += gameData.score; + this.sessionStats.maxLength = Math.max(this.sessionStats.maxLength, gameData.length); + this.sessionStats.maxLevel = Math.max(this.sessionStats.maxLevel, gameData.level); + this.sessionStats.totalTime += gameData.gameTime; + + // 保存会话统计 + localStorage.setItem('snakeSessionStats', JSON.stringify(this.sessionStats)); + + // 检查是否进入高分榜 + this.checkHighScore(gameData); + + // 显示统计信息 + this.displaySessionStats(); + } + + handleFoodEaten(foodData) { + // 可以记录特殊食物统计等 + console.log('食物被吃掉:', foodData); + } + + handleLevelUp(levelData) { + // 等级提升统计 + console.log('等级提升到:', levelData.level); + } + + checkHighScore(gameData) { + const highScoreEntry = { + score: gameData.score, + length: gameData.length, + level: gameData.level, + time: gameData.gameTime, + date: new Date().toLocaleDateString(), + timestamp: Date.now() + }; + + // 添加到高分榜 + this.highScores.push(highScoreEntry); + + // 按分数排序(降序) + this.highScores.sort((a, b) => b.score - a.score); + + // 只保留前10名 + this.highScores = this.highScores.slice(0, 10); + + // 保存到本地存储 + localStorage.setItem('snakeHighScores', JSON.stringify(this.highScores)); + + // 显示高分榜 + this.displayHighScores(); + } + + displaySessionStats() { + const statsElement = document.createElement('div'); + statsElement.className = 'session-stats'; + statsElement.innerHTML = ` +

本次会话统计

+

游戏次数: ${this.sessionStats.gamesPlayed}

+

总得分: ${this.sessionStats.totalScore}

+

最高长度: ${this.sessionStats.maxLength}

+

最高等级: ${this.sessionStats.maxLevel}

+

总游戏时间: ${Math.floor(this.sessionStats.totalTime / 60)}分钟

+

平均得分: ${Math.round(this.sessionStats.totalScore / this.sessionStats.gamesPlayed)}

+ `; + + // 添加到游戏结束模态框 + const statsContainer = document.querySelector('.stats'); + if (statsContainer && !document.querySelector('.session-stats')) { + statsContainer.appendChild(statsElement); + } + } + + displayHighScores() { + const highScoresElement = document.createElement('div'); + highScoresElement.className = 'high-scores'; + + if (this.highScores.length > 0) { + highScoresElement.innerHTML = ` +

🏆 高分榜

+ ${this.highScores.map((score, index) => ` +
+ ${index + 1}. + ${score.score}分 + 长度:${score.length} + ${score.date} +
+ `).join('')} + `; + } else { + highScoresElement.innerHTML = '

暂无高分记录

'; + } + + // 添加到游戏结束模态框 + const modalContent = document.querySelector('.modal-content'); + if (modalContent && !document.querySelector('.high-scores')) { + modalContent.appendChild(highScoresElement); + } + } + + getAchievements(gameData) { + const achievements = []; + + if (gameData.score >= 100) achievements.push('百分达人'); + if (gameData.length >= 20) achievements.push('长蛇之王'); + if (gameData.level >= 5) achievements.push('等级大师'); + if (gameData.gameTime >= 300) achievements.push('持久战将'); + if (gameData.score >= 50 && gameData.gameTime <= 60) achievements.push('速通高手'); + + return achievements; + } + + // 工具方法:格式化时间 + formatTime(seconds) { + const mins = Math.floor(seconds / 60); + const secs = seconds % 60; + return `${mins}分${secs}秒`; + } + + // 清除统计 + clearStatistics() { + this.highScores = []; + this.sessionStats = { + gamesPlayed: 0, + totalScore: 0, + maxLength: 0, + maxLevel: 0, + totalTime: 0 + }; + + localStorage.removeItem('snakeHighScores'); + localStorage.removeItem('snakeSessionStats'); + + console.log('统计信息已清除'); + } +} + +// 扩展游戏核心类,添加统计事件触发 +SnakeGame.prototype.showGameOver = function() { + const modal = document.getElementById('gameOverModal'); + const gameTime = Math.floor((Date.now() - this.startTime) / 1000); + + document.getElementById('finalScore').textContent = this.score; + document.getElementById('finalLength').textContent = this.snake.length; + document.getElementById('finalLevel').textContent = this.level; + document.getElementById('gameTime').textContent = gameTime; + document.getElementById('foodEaten').textContent = this.foodEaten; + + // 触发游戏结束事件 + const gameOverEvent = new CustomEvent('gameOver', { + detail: { + score: this.score, + length: this.snake.length, + level: this.level, + gameTime: gameTime, + foodEaten: this.foodEaten + } + }); + document.dispatchEvent(gameOverEvent); + + modal.style.display = 'flex'; +}; + +// 初始化统计模块 +let gameStats; + +document.addEventListener('DOMContentLoaded', () => { + gameStats = new GameStatistics(); +}); + +// 添加CSS样式 +const statsStyles = ` +.session-stats { + margin-top: 20px; + padding: 15px; + background: linear-gradient(135deg, #fdfcfb 0%, #e2d1c3 100%); + border-radius: 10px; + border: 2px solid #d4a76a; +} + +.session-stats h3 { + color: #8b4513; + margin-bottom: 10px; + text-align: center; +} + +.session-stats p { + margin: 5px 0; + color: #654321; + font-size: 0.9rem; +} + +.high-scores { + margin-top: 20px; + padding: 15px; + background: linear-gradient(135deg, #fff1eb 0%, #ace0f9 100%); + border-radius: 10px; + border: 2px solid #4682b4; +} + +.high-scores h3 { + color: #2c5282; + margin-bottom: 10px; + text-align: center; +} + +.score-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 0; + border-bottom: 1px solid #cbd5e0; +} + +.score-item:last-child { + border-bottom: none; +} + +.score-item.first-place { + background: linear-gradient(135deg, #fceabb 0%, #f8b500 100%); + border-radius: 5px; + padding: 8px; + margin: -8px -8px 8px -8px; +} + +.rank { + font-weight: bold; + color: #2d3748; + min-width: 30px; +} + +.score { + font-weight: bold; + color: #e53e3e; + min-width: 60px; +} + +.length { + color: #4a5568; + font-size: 0.8rem; + min-width: 60px; +} + +.date { + color: #718096; + font-size: 0.7rem; + min-width: 60px; + text-align: right; +} +`; + +// 注入样式 +const styleSheet = document.createElement('style'); +styleSheet.textContent = statsStyles; +document.head.appendChild(styleSheet); \ No newline at end of file diff --git a/InfoGenie-frontend/public/smallgame/贪吃蛇/index.html b/InfoGenie-frontend/public/smallgame/贪吃蛇/index.html new file mode 100644 index 00000000..2302c8a5 --- /dev/null +++ b/InfoGenie-frontend/public/smallgame/贪吃蛇/index.html @@ -0,0 +1,61 @@ + + + + + + 贪吃蛇游戏 + + + +
+
+

贪吃蛇

+
+ 分数: 0 + 长度: 3 + 等级: 1 +
+
+ +
+ +
+ +
+
+ +
+
+ + + +
+
+ +
+
+ +
+

使用方向键或触摸按钮控制蛇的方向

+
+
+ + + + + + + + \ No newline at end of file diff --git a/InfoGenie-frontend/public/smallgame/贪吃蛇/styles.css b/InfoGenie-frontend/public/smallgame/贪吃蛇/styles.css new file mode 100644 index 00000000..edc0d223 --- /dev/null +++ b/InfoGenie-frontend/public/smallgame/贪吃蛇/styles.css @@ -0,0 +1,258 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Arial', sans-serif; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + min-height: 100vh; + display: flex; + justify-content: center; + align-items: center; + touch-action: manipulation; + -webkit-tap-highlight-color: transparent; +} + +.game-container { + background: rgba(255, 255, 255, 0.95); + border-radius: 20px; + padding: 20px; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3); + max-width: 400px; + width: 95%; + margin: 20px auto; +} + +.game-header { + text-align: center; + margin-bottom: 20px; +} + +.game-header h1 { + color: #333; + font-size: 2.5rem; + margin-bottom: 15px; + text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1); +} + +.score-board { + display: flex; + justify-content: space-around; + background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); + padding: 12px; + border-radius: 15px; + color: white; + font-weight: bold; + font-size: 1.1rem; +} + +.score-board span { + display: flex; + flex-direction: column; + align-items: center; +} + +.game-canvas-container { + display: flex; + justify-content: center; + margin: 20px 0; +} + +#gameCanvas { + border: 3px solid #333; + border-radius: 10px; + background: #222; + box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2); +} + +.game-controls { + margin: 20px 0; +} + +.control-row { + display: flex; + justify-content: center; + margin: 8px 0; +} + +.control-btn { + width: 70px; + height: 70px; + margin: 0 10px; + border: none; + border-radius: 50%; + background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); + color: white; + font-size: 1.5rem; + font-weight: bold; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); +} + +.control-btn:hover { + transform: scale(1.1); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3); +} + +.control-btn:active { + transform: scale(0.95); +} + +#pauseBtn { + background: linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%); + color: #333; + font-size: 1.2rem; +} + +.game-instructions { + text-align: center; + color: #666; + font-size: 0.9rem; + margin-top: 15px; +} + +.modal { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.8); + z-index: 1000; + justify-content: center; + align-items: center; +} + +.modal-content { + background: white; + padding: 30px; + border-radius: 20px; + text-align: center; + max-width: 400px; + width: 90%; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4); +} + +.modal-content h2 { + color: #e74c3c; + margin-bottom: 20px; + font-size: 2rem; +} + +.stats p { + margin: 10px 0; + font-size: 1.1rem; + color: #333; +} + +.stats span { + font-weight: bold; + color: #e74c3c; +} + +.restart-btn { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border: none; + padding: 15px 30px; + border-radius: 25px; + font-size: 1.2rem; + font-weight: bold; + cursor: pointer; + margin-top: 20px; + transition: all 0.3s ease; +} + +.restart-btn:hover { + transform: scale(1.05); + box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3); +} + +/* 手机端优化 */ +@media (max-width: 768px) { + .game-container { + padding: 15px; + margin: 10px; + border-radius: 15px; + } + + .game-header h1 { + font-size: 2rem; + } + + .score-board { + font-size: 0.9rem; + padding: 8px; + } + + .control-btn { + width: 60px; + height: 60px; + font-size: 1.3rem; + margin: 0 8px; + } + + #pauseBtn { + font-size: 1rem; + } + + #gameCanvas { + width: 280px; + height: 400px; + } +} + +/* 超小屏幕优化 */ +@media (max-width: 480px) { + .game-header h1 { + font-size: 1.8rem; + } + + .score-board { + flex-direction: column; + gap: 5px; + } + + .control-btn { + width: 50px; + height: 50px; + font-size: 1.1rem; + margin: 0 5px; + } + + #gameCanvas { + width: 250px; + height: 350px; + } + + .modal-content { + padding: 20px; + } + + .modal-content h2 { + font-size: 1.5rem; + } +} + +/* 防止文本选择 */ +.control-btn, .restart-btn { + user-select: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; +} + +/* 动画效果 */ +@keyframes pulse { + 0% { transform: scale(1); } + 50% { transform: scale(1.05); } + 100% { transform: scale(1); } +} + +.score-board { + animation: pulse 2s infinite; +} \ No newline at end of file diff --git a/frontend/public/sw.js b/InfoGenie-frontend/public/sw.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/public/sw.js rename to InfoGenie-frontend/public/sw.js diff --git a/frontend/setting.json b/InfoGenie-frontend/setting.json old mode 100755 new mode 100644 similarity index 100% rename from frontend/setting.json rename to InfoGenie-frontend/setting.json diff --git a/frontend/src/App.js b/InfoGenie-frontend/src/App.js old mode 100755 new mode 100644 similarity index 95% rename from frontend/src/App.js rename to InfoGenie-frontend/src/App.js index ff160603..ae2d7115 --- a/frontend/src/App.js +++ b/InfoGenie-frontend/src/App.js @@ -9,6 +9,7 @@ import LoginPage from './pages/LoginPage'; import Api60sPage from './pages/Api60sPage'; import SmallGamePage from './pages/SmallGamePage'; import AiModelPage from './pages/AiModelPage'; +import UserProfilePage from './pages/UserProfilePage'; // 公共组件 import Header from './components/Header'; @@ -48,6 +49,7 @@ function App() { } /> } /> } /> + } /> {/* 通配符路由 - 所有未匹配的路径都重定向到首页 */} } /> diff --git a/frontend/src/components/Footer.js b/InfoGenie-frontend/src/components/Footer.js old mode 100755 new mode 100644 similarity index 99% rename from frontend/src/components/Footer.js rename to InfoGenie-frontend/src/components/Footer.js index a567f4f0..ae2af128 --- a/frontend/src/components/Footer.js +++ b/InfoGenie-frontend/src/components/Footer.js @@ -56,7 +56,7 @@ const FooterLink = styled.a` transition: color 0.2s ease; &:hover { - color: #667eea; + color: #4ade80; } `; diff --git a/frontend/src/components/Header.js b/InfoGenie-frontend/src/components/Header.js old mode 100755 new mode 100644 similarity index 97% rename from frontend/src/components/Header.js rename to InfoGenie-frontend/src/components/Header.js index 3f1bebdf..ac71e8cc --- a/frontend/src/components/Header.js +++ b/InfoGenie-frontend/src/components/Header.js @@ -199,7 +199,7 @@ const MobileNavLink = styled(Link)` transition: color 0.2s ease; &:hover { - color: #667eea; + color: #4ade80; } &:last-child { @@ -236,9 +236,9 @@ const Header = () => { diff --git a/frontend/src/components/Navigation.js b/InfoGenie-frontend/src/components/Navigation.js old mode 100755 new mode 100644 similarity index 94% rename from frontend/src/components/Navigation.js rename to InfoGenie-frontend/src/components/Navigation.js index 4a6484f7..b5babd14 --- a/frontend/src/components/Navigation.js +++ b/InfoGenie-frontend/src/components/Navigation.js @@ -1,7 +1,7 @@ import React from 'react'; import { Link, useLocation } from 'react-router-dom'; import styled from 'styled-components'; -import { FiHome, FiActivity, FiGrid, FiCpu } from 'react-icons/fi'; +import { FiHome, FiActivity, FiGrid, FiCpu, FiUser } from 'react-icons/fi'; const NavigationContainer = styled.nav` position: fixed; @@ -90,6 +90,11 @@ const Navigation = () => { path: '/aimodel', icon: FiCpu, text: 'AI工具' + }, + { + path: '/profile', + icon: FiUser, + text: '个人中心' } ]; diff --git a/frontend/src/config/StaticPageConfig.js b/InfoGenie-frontend/src/config/StaticPageConfig.js similarity index 72% rename from frontend/src/config/StaticPageConfig.js rename to InfoGenie-frontend/src/config/StaticPageConfig.js index 299d0c82..ebac76ed 100644 --- a/frontend/src/config/StaticPageConfig.js +++ b/InfoGenie-frontend/src/config/StaticPageConfig.js @@ -1,12 +1,13 @@ // 静态页面配置文件 // 统一管理所有静态网页的链接和配置信息 +//AI模型工具 export const AI_MODEL_APPS = [ { title: 'AI变量命名助手', description: '智能变量命名工具,帮助开发者快速生成规范的变量名', link: '/aimodelapp/AI变量命名助手/index.html', - gradient: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', + gradient: 'linear-gradient(135deg, #4ade80 0%, #22c55e 100%)', icon: '🤖' }, { @@ -22,7 +23,35 @@ export const AI_MODEL_APPS = [ link: '/aimodelapp/AI姓名评测/index.html', gradient: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)', icon: '👤' - } + }, + { + title: 'AI翻译助手', + description: '基于AI的翻译工具', + link: '/aimodelapp/AI语言翻译助手/index.html', + gradient: 'linear-gradient(135deg,rgb(80, 77, 243) 0%,rgb(30, 211, 111) 100%)', + icon: '🌍' + }, + { + title: 'AI文章转文言文', + description: '基于AI的文章转文言文工具', + link: '/aimodelapp/AI文章转文言文/index.html', + gradient: 'linear-gradient(135deg,rgb(186, 248, 70) 0%,rgb(255, 208, 0) 100%)', + icon: '📝' + }, + { + title: 'AI生成表情包', + description: '基于AI的生成表情包工具', + link: '/aimodelapp/AI生成表情包/index.html', + gradient: 'linear-gradient(135deg,rgb(186, 248, 70) 0%,rgb(34, 157, 238) 100%)', + icon: '📸' + }, + { + title: 'AI生成Linux命令', + description: '基于AI的生成Linux命令工具', + link: '/aimodelapp/AI生成Linux命令/index.html', + gradient: 'linear-gradient(135deg,rgb(128, 180, 32) 0%,rgb(29, 199, 162) 100%)', + icon: '🐧' + }, ]; export const SMALL_GAMES = [ @@ -44,9 +73,23 @@ export const SMALL_GAMES = [ title: '俄罗斯方块', description: '经典落块消除游戏,永恒的经典之作', link: '/smallgame/俄罗斯方块/index.html', - gradient: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', + gradient: 'linear-gradient(135deg, #4ade80 0%, #22c55e 100%)', icon: '🧩' - } + }, + { + title: '贪吃蛇', + description: '经典贪吃蛇游戏,考验你的反应速度和手指协调', + link: '/smallgame/贪吃蛇/index.html', + gradient: 'linear-gradient(135deg,rgb(37, 132, 240) 0%, #f5576c 100%)', + icon: '🐍' + }, + { + title: '扫雷', + description: '经典扫雷游戏,考验你的反应速度和手指协调', + link: '/smallgame/扫雷/index.html', + gradient: 'linear-gradient(135deg,rgb(37, 132, 240) 0%, #f5576c 100%)', + icon: '💣' + }, ]; export const API_60S_CATEGORIES = [ @@ -62,7 +105,12 @@ export const API_60S_CATEGORIES = [ { title: '网易云榜单', link: '/60sapi/热搜榜单/网易云榜单/index.html' }, { title: '微博热搜榜', link: '/60sapi/热搜榜单/微博热搜榜/index.html' }, { title: '知乎热门话题', link: '/60sapi/热搜榜单/知乎热门话题/index.html' }, - { title: 'Hacker News 榜单', link: '/60sapi/热搜榜单/Hacker News 榜单/index.html' } + { title: 'Hacker News 榜单', link: '/60sapi/热搜榜单/Hacker News 榜单/index.html' }, + { title: '小红书热点', link: '/60sapi/热搜榜单/小红书热点/index.html' }, + { title: '百度实时热搜', link: '/60sapi/热搜榜单/百度实时热搜/index.html' }, + { title: '百度电视剧榜', link: '/60sapi/热搜榜单/百度电视剧榜/index.html' }, + { title: '百度贴吧话题榜', link: '/60sapi/热搜榜单/百度贴吧话题榜/index.html' }, + { title: '懂车帝热搜', link: '/60sapi/热搜榜单/懂车帝热搜/index.html' }, ] }, { @@ -93,7 +141,8 @@ export const API_60S_CATEGORIES = [ { title: '随机密码生成器', link: '/60sapi/实用功能/随机密码生成器/index.html' }, { title: '随机颜色', link: '/60sapi/实用功能/随机颜色/index.html' }, { title: '天气预报', link: '/60sapi/实用功能/天气预报/index.html' }, - { title: 'EpicGames免费游戏', link: '/60sapi/实用功能/EpicGames免费游戏/index.html' } + { title: 'EpicGames免费游戏', link: '/60sapi/实用功能/EpicGames免费游戏/index.html' }, + { title: '在线机器翻译', link: '/60sapi/实用功能/在线翻译/index.html' }, ] }, { diff --git a/frontend/src/contexts/UserContext.js b/InfoGenie-frontend/src/contexts/UserContext.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/src/contexts/UserContext.js rename to InfoGenie-frontend/src/contexts/UserContext.js diff --git a/frontend/src/index.js b/InfoGenie-frontend/src/index.js old mode 100755 new mode 100644 similarity index 100% rename from frontend/src/index.js rename to InfoGenie-frontend/src/index.js diff --git a/frontend/src/md/前端邮件功能测试指南.md b/InfoGenie-frontend/src/md/前端邮件功能测试指南.md old mode 100755 new mode 100644 similarity index 100% rename from frontend/src/md/前端邮件功能测试指南.md rename to InfoGenie-frontend/src/md/前端邮件功能测试指南.md diff --git a/frontend/src/pages/AiModelPage.js b/InfoGenie-frontend/src/pages/AiModelPage.js old mode 100755 new mode 100644 similarity index 93% rename from frontend/src/pages/AiModelPage.js rename to InfoGenie-frontend/src/pages/AiModelPage.js index b7d43c48..e89157bb --- a/frontend/src/pages/AiModelPage.js +++ b/InfoGenie-frontend/src/pages/AiModelPage.js @@ -22,7 +22,7 @@ const PageHeader = styled.div` text-align: center; margin-bottom: 40px; padding: 40px 20px; - background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%); + background: linear-gradient(135deg, rgba(74, 222, 128, 0.1) 0%, rgba(34, 197, 94, 0.1) 100%); border-radius: 16px; `; @@ -76,7 +76,7 @@ const AppCard = styled.div` &:hover { transform: translateY(-4px); box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); - border-color: #667eea; + border-color: #4ade80; } `; @@ -96,7 +96,7 @@ const AppTitle = styled.h3` const AppIcon = styled.div` font-size: 24px; - color: #667eea; + color: #4ade80; `; const AppDescription = styled.p` @@ -116,11 +116,11 @@ const AppTheme = styled.div` width: 40px; height: 40px; border-radius: 8px; - background: ${props => props.gradient}; + background: ${props => props.$gradient}; `; const LaunchButton = styled.button` - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + background: linear-gradient(135deg, #4ade80 0%, #22c55e 100%); color: white; border: none; padding: 8px 16px; @@ -135,7 +135,7 @@ const LaunchButton = styled.button` &:hover { transform: translateY(-1px); - box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3); + box-shadow: 0 4px 12px rgba(74, 222, 128, 0.3); } `; @@ -159,7 +159,7 @@ const LoginText = styled.p` `; const LoginButton = styled.button` - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + background: linear-gradient(135deg, #4ade80 0%, #22c55e 100%); color: white; border: none; padding: 14px 32px; @@ -174,7 +174,7 @@ const LoginButton = styled.button` &:hover { transform: translateY(-1px); - box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3); + box-shadow: 0 4px 12px rgba(74, 222, 128, 0.3); } `; @@ -203,7 +203,7 @@ const EmbeddedContent = styled.div` `; const EmbeddedHeader = styled.div` - background: linear-gradient(135deg, #667eea, #764ba2); + background: linear-gradient(135deg, #4ade80, #22c55e); color: white; padding: 15px 20px; padding-top: max(15px, env(safe-area-inset-top)); @@ -346,7 +346,7 @@ const AiModelPage = () => { - -
-

生成的古诗

-
正在创作中,请稍候...
-
点击"生成古诗"按钮,AI将为您创作优美的古诗
-
- - - - - - \ No newline at end of file diff --git a/frontend/public/aimodelapp/AI变量命名助手/env.js b/frontend/public/aimodelapp/AI变量命名助手/env.js deleted file mode 100755 index 4b00731e..00000000 --- a/frontend/public/aimodelapp/AI变量命名助手/env.js +++ /dev/null @@ -1,68 +0,0 @@ -// AI变量命名助手配置文件 -const CONFIG = { - // GitHub Models API 配置 - GITHUB_TOKEN: '', - API_URL: 'https://models.github.ai/inference/chat/completions', - MODEL_NAME: 'openai/gpt-4o-mini', - - // AI提示词模板 - createNamingPrompt: (description) => { - return `你是一个专业的变量命名助手。请根据以下描述为变量生成合适的名称: - -描述:${description} - -请为每种命名规范生成3个变量名建议: -1. camelCase (驼峰命名法) -2. PascalCase (帕斯卡命名法) -3. snake_case (下划线命名法) -4. kebab-case (短横线命名法) -5. CONSTANT_CASE (常量命名法) - -要求: -- 变量名要准确反映功能和用途 -- 严格遵循各自的命名规范 -- 避免使用缩写,除非是广泛认知的缩写 -- 名称要简洁但具有描述性 -- 考虑代码的可读性和维护性 - -请按以下JSON格式返回: -{ - "suggestions": { - "camelCase": [ - {"name": "变量名1", "description": "解释说明1"}, - {"name": "变量名2", "description": "解释说明2"}, - {"name": "变量名3", "description": "解释说明3"} - ], - "PascalCase": [ - {"name": "变量名1", "description": "解释说明1"}, - {"name": "变量名2", "description": "解释说明2"}, - {"name": "变量名3", "description": "解释说明3"} - ], - "snake_case": [ - {"name": "变量名1", "description": "解释说明1"}, - {"name": "变量名2", "description": "解释说明2"}, - {"name": "变量名3", "description": "解释说明3"} - ], - "kebab-case": [ - {"name": "变量名1", "description": "解释说明1"}, - {"name": "变量名2", "description": "解释说明2"}, - {"name": "变量名3", "description": "解释说明3"} - ], - "CONSTANT_CASE": [ - {"name": "变量名1", "description": "解释说明1"}, - {"name": "变量名2", "description": "解释说明2"}, - {"name": "变量名3", "description": "解释说明3"} - ] - } -} - -只返回JSON格式的结果,不要包含其他文字。`; - } -}; - -// 导出配置 -if (typeof module !== 'undefined' && module.exports) { - module.exports = CONFIG; -} else { - window.CONFIG = CONFIG; -} \ No newline at end of file diff --git a/frontend/public/aimodelapp/AI姓名评测/env.js b/frontend/public/aimodelapp/AI姓名评测/env.js deleted file mode 100755 index 8b6efdf1..00000000 --- a/frontend/public/aimodelapp/AI姓名评测/env.js +++ /dev/null @@ -1,47 +0,0 @@ -// AI姓名评测配置文件 -const CONFIG = { - // GitHub API 配置 - GITHUB_TOKEN: '', - endpoint: 'https://models.github.ai/inference/chat/completions', - model: 'deepseek/DeepSeek-V3-0324', - - // 专业的姓名分析提示词 - createNameAnalysisPrompt: (name) => { - return `你是一位专业的姓名学专家和语言学家,请对输入的姓名进行全面分析。请直接输出分析结果,不要包含任何思考过程或标签。 - -姓名:${name} - -请按照以下格式严格输出分析结果: - -【稀有度评分】 -评分:X% -评价:[对稀有度的详细说明,包括姓氏和名字的常见程度分析] - -【音韵评价】 -评分:X% -评价:[对音韵美感的分析,包括声调搭配、读音流畅度、音律和谐度等] - -【含义解读】 -[详细分析姓名的寓意内涵,包括: -1. 姓氏的历史渊源和文化背景 -2. 名字各字的含义和象征 -3. 整体姓名的寓意组合 -4. 可能体现的父母期望或文化内涵 -5. 与传统文化、诗词典故的关联等] - -要求: -1. 评分必须是1-100的整数百分比,要有明显区分度,避免雷同 -2. 分析要专业、客观、有依据,评分要根据实际情况有所差异 -3. 含义解读要详细深入,至少150字 -4. 严格按照上述格式输出,不要添加思考过程、标签或其他内容 -5. 如果是生僻字或罕见姓名,要特别说明 -6. 直接输出最终结果,不要显示推理过程`; - } -}; - -// 导出配置 -if (typeof module !== 'undefined' && module.exports) { - module.exports = CONFIG; -} else { - window.CONFIG = CONFIG; -} \ No newline at end of file diff --git a/frontend/public/aimodelapp/AI姓名评测/styles.css b/frontend/public/aimodelapp/AI姓名评测/styles.css deleted file mode 100755 index dc1325ec..00000000 --- a/frontend/public/aimodelapp/AI姓名评测/styles.css +++ /dev/null @@ -1,249 +0,0 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - font-family: 'Microsoft YaHei', '微软雅黑', Arial, sans-serif; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - min-height: 100vh; - padding: 20px; - color: #333; -} - -.container { - max-width: 700px; - margin: 0 auto; - background: rgba(255, 255, 255, 0.95); - border-radius: 20px; - padding: 30px; - box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); - backdrop-filter: blur(10px); -} - -.header { - text-align: center; - margin-bottom: 30px; -} - -.title { - font-size: 2.5rem; - color: #4a5568; - margin-bottom: 10px; - font-weight: 300; - letter-spacing: 2px; -} - -.subtitle { - color: #718096; - font-size: 1rem; - margin-bottom: 20px; -} - -.form-group { - margin-bottom: 25px; -} - -.form-label { - display: block; - margin-bottom: 8px; - font-weight: 500; - color: #4a5568; - font-size: 1rem; -} - -.form-input { - width: 100%; - padding: 15px; - border: 2px solid #e2e8f0; - border-radius: 12px; - font-size: 1rem; - transition: all 0.3s ease; - background: #f7fafc; - text-align: center; -} - -.form-input:focus { - outline: none; - border-color: #667eea; - background: #fff; - box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); -} - -.btn { - width: 100%; - padding: 15px; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - color: white; - border: none; - border-radius: 12px; - font-size: 1.1rem; - font-weight: 500; - cursor: pointer; - transition: all 0.3s ease; - margin-bottom: 25px; -} - -.btn:hover { - transform: translateY(-2px); - box-shadow: 0 10px 25px rgba(102, 126, 234, 0.3); -} - -.btn:active { - transform: translateY(0); -} - -.btn:disabled { - opacity: 0.6; - cursor: not-allowed; - transform: none; -} - -.result-section { - margin-top: 30px; -} - -.result-title { - font-size: 1.3rem; - color: #4a5568; - margin-bottom: 20px; - text-align: center; - font-weight: 500; -} - -.loading { - display: none; - text-align: center; - color: #667eea; - font-style: italic; - margin-bottom: 20px; -} - -.result-container { - display: grid; - gap: 20px; - grid-template-columns: 1fr; -} - -.result-card { - background: #f7fafc; - border: 2px solid #e2e8f0; - border-radius: 12px; - padding: 20px; - transition: all 0.3s ease; -} - -.result-card:hover { - border-color: #667eea; - box-shadow: 0 5px 15px rgba(102, 126, 234, 0.1); -} - -.card-title { - font-size: 1.1rem; - color: #4a5568; - margin-bottom: 15px; - text-align: center; - font-weight: 600; -} - -.score-display { - font-size: 2.5rem; - font-weight: bold; - text-align: center; - margin-bottom: 10px; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; -} - -.score-desc { - text-align: center; - color: #718096; - font-size: 0.9rem; - line-height: 1.5; -} - -.meaning-content { - color: #2d3748; - line-height: 1.8; - font-size: 1rem; - text-align: left; - white-space: pre-wrap; -} - -.error { - color: #e53e3e; - background: #fed7d7; - border: 1px solid #feb2b2; - padding: 15px; - border-radius: 8px; - margin-top: 15px; -} - -/* 平板和桌面端优化 */ -@media (min-width: 768px) { - .result-container { - grid-template-columns: 1fr 1fr; - } - - .result-card:last-child { - grid-column: 1 / -1; - } -} - -/* 手机端优化 */ -@media (max-width: 768px) { - body { - padding: 10px; - } - - .container { - padding: 20px; - margin: 10px; - } - - .title { - font-size: 2rem; - } - - .form-input { - padding: 12px; - } - - .btn { - padding: 12px; - } - - .result-card { - padding: 15px; - } - - .score-display { - font-size: 2rem; - } -} - -@media (max-width: 480px) { - .title { - font-size: 1.8rem; - letter-spacing: 1px; - } - - .container { - padding: 15px; - } - - .result-card { - padding: 12px; - } - - .score-display { - font-size: 1.8rem; - } - - .meaning-content { - font-size: 0.9rem; - } -} \ No newline at end of file diff --git a/frontend/src/utils/helpers.js b/frontend/src/utils/helpers.js deleted file mode 100755 index 3cf1dd76..00000000 --- a/frontend/src/utils/helpers.js +++ /dev/null @@ -1,310 +0,0 @@ -// 工具函数集合 - -/** - * 格式化时间 - * @param {string|Date} date - 日期 - * @param {string} format - 格式 ('datetime', 'date', 'time') - * @returns {string} 格式化后的时间字符串 - */ -export const formatTime = (date, format = 'datetime') => { - if (!date) return ''; - - const d = new Date(date); - const year = d.getFullYear(); - const month = String(d.getMonth() + 1).padStart(2, '0'); - const day = String(d.getDate()).padStart(2, '0'); - const hours = String(d.getHours()).padStart(2, '0'); - const minutes = String(d.getMinutes()).padStart(2, '0'); - const seconds = String(d.getSeconds()).padStart(2, '0'); - - switch (format) { - case 'date': - return `${year}-${month}-${day}`; - case 'time': - return `${hours}:${minutes}:${seconds}`; - case 'datetime': - default: - return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; - } -}; - -/** - * 获取相对时间 - * @param {string|Date} date - 日期 - * @returns {string} 相对时间字符串 - */ -export const getRelativeTime = (date) => { - if (!date) return ''; - - const now = new Date(); - const target = new Date(date); - const diff = now - target; - - const minute = 60 * 1000; - const hour = 60 * minute; - const day = 24 * hour; - - if (diff < minute) { - return '刚刚'; - } else if (diff < hour) { - return `${Math.floor(diff / minute)}分钟前`; - } else if (diff < day) { - return `${Math.floor(diff / hour)}小时前`; - } else if (diff < 7 * day) { - return `${Math.floor(diff / day)}天前`; - } else { - return formatTime(date, 'date'); - } -}; - -/** - * 防抖函数 - * @param {Function} func - 要防抖的函数 - * @param {number} wait - 等待时间(毫秒) - * @returns {Function} 防抖后的函数 - */ -export const debounce = (func, wait) => { - let timeout; - return function executedFunction(...args) { - const later = () => { - clearTimeout(timeout); - func(...args); - }; - clearTimeout(timeout); - timeout = setTimeout(later, wait); - }; -}; - -/** - * 节流函数 - * @param {Function} func - 要节流的函数 - * @param {number} limit - 限制时间(毫秒) - * @returns {Function} 节流后的函数 - */ -export const throttle = (func, limit) => { - let inThrottle; - return function executedFunction(...args) { - if (!inThrottle) { - func.apply(this, args); - inThrottle = true; - setTimeout(() => inThrottle = false, limit); - } - }; -}; - -/** - * 深拷贝对象 - * @param {any} obj - 要拷贝的对象 - * @returns {any} 深拷贝后的对象 - */ -export const deepClone = (obj) => { - if (obj === null || typeof obj !== 'object') return obj; - if (obj instanceof Date) return new Date(obj.getTime()); - if (obj instanceof Array) return obj.map(item => deepClone(item)); - if (typeof obj === 'object') { - const clonedObj = {}; - for (const key in obj) { - if (obj.hasOwnProperty(key)) { - clonedObj[key] = deepClone(obj[key]); - } - } - return clonedObj; - } -}; - -/** - * 生成唯一ID - * @returns {string} 唯一ID - */ -export const generateId = () => { - return Date.now().toString(36) + Math.random().toString(36).substr(2); -}; - -/** - * 检查是否为移动设备 - * @returns {boolean} 是否为移动设备 - */ -export const isMobile = () => { - return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); -}; - -/** - * 获取屏幕尺寸类型 - * @returns {string} 屏幕尺寸类型 ('mobile', 'tablet', 'desktop') - */ -export const getScreenSize = () => { - const width = window.innerWidth; - if (width < 768) return 'mobile'; - if (width < 1024) return 'tablet'; - return 'desktop'; -}; - -/** - * 滚动到顶部 - * @param {number} duration - 动画持续时间(毫秒) - */ -export const scrollToTop = (duration = 300) => { - const start = window.pageYOffset; - const startTime = 'now' in window.performance ? performance.now() : new Date().getTime(); - - const animateScroll = (currentTime) => { - const timeElapsed = currentTime - startTime; - const progress = Math.min(timeElapsed / duration, 1); - - window.scroll(0, start * (1 - progress)); - - if (progress < 1) { - requestAnimationFrame(animateScroll); - } - }; - - requestAnimationFrame(animateScroll); -}; - -/** - * 格式化数字 - * @param {number} num - 数字 - * @returns {string} 格式化后的数字字符串 - */ -export const formatNumber = (num) => { - if (num >= 100000000) { - return (num / 100000000).toFixed(1) + '亿'; - } else if (num >= 10000) { - return (num / 10000).toFixed(1) + '万'; - } else if (num >= 1000) { - return (num / 1000).toFixed(1) + 'K'; - } - return num.toString(); -}; - -/** - * 验证手机号 - * @param {string} phone - 手机号 - * @returns {boolean} 是否有效 - */ -export const validatePhone = (phone) => { - const phoneRegex = /^1[3-9]\d{9}$/; - return phoneRegex.test(phone); -}; - -/** - * 验证用户名 - * @param {string} username - 用户名 - * @returns {boolean} 是否有效 - */ -export const validateUsername = (username) => { - const usernameRegex = /^[a-zA-Z0-9_]{6,20}$/; - return usernameRegex.test(username); -}; - -/** - * 验证密码强度 - * @param {string} password - 密码 - * @returns {object} 验证结果 - */ -export const validatePassword = (password) => { - const result = { - valid: false, - strength: 'weak', - message: '' - }; - - if (password.length < 6) { - result.message = '密码长度至少6位'; - return result; - } - - if (password.length > 20) { - result.message = '密码长度不能超过20位'; - return result; - } - - let strength = 0; - - // 检查是否包含小写字母 - if (/[a-z]/.test(password)) strength++; - - // 检查是否包含大写字母 - if (/[A-Z]/.test(password)) strength++; - - // 检查是否包含数字 - if (/\d/.test(password)) strength++; - - // 检查是否包含特殊字符 - if (/[!@#$%^&*(),.?":{}|<>]/.test(password)) strength++; - - if (strength >= 3) { - result.strength = 'strong'; - result.message = '密码强度:强'; - } else if (strength >= 2) { - result.strength = 'medium'; - result.message = '密码强度:中等'; - } else { - result.strength = 'weak'; - result.message = '密码强度:弱'; - } - - result.valid = true; - return result; -}; - -/** - * 本地存储工具 - */ -export const storage = { - set: (key, value) => { - try { - localStorage.setItem(key, JSON.stringify(value)); - } catch (error) { - console.error('存储数据失败:', error); - } - }, - - get: (key, defaultValue = null) => { - try { - const item = localStorage.getItem(key); - return item ? JSON.parse(item) : defaultValue; - } catch (error) { - console.error('读取数据失败:', error); - return defaultValue; - } - }, - - remove: (key) => { - try { - localStorage.removeItem(key); - } catch (error) { - console.error('删除数据失败:', error); - } - }, - - clear: () => { - try { - localStorage.clear(); - } catch (error) { - console.error('清空数据失败:', error); - } - } -}; - -/** - * URL参数工具 - */ -export const urlParams = { - get: (param) => { - const urlParams = new URLSearchParams(window.location.search); - return urlParams.get(param); - }, - - set: (param, value) => { - const url = new URL(window.location); - url.searchParams.set(param, value); - window.history.pushState({}, '', url); - }, - - remove: (param) => { - const url = new URL(window.location); - url.searchParams.delete(param); - window.history.pushState({}, '', url); - } -}; diff --git a/start_backend.bat b/start_backend.bat deleted file mode 100755 index f98ddefd..00000000 --- a/start_backend.bat +++ /dev/null @@ -1,3 +0,0 @@ -@echo off -cd /d "E:\Python\InfoGenie\backend" -python app.py \ No newline at end of file diff --git a/start_backend.sh b/start_backend.sh deleted file mode 100755 index 29056eff..00000000 --- a/start_backend.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -cd /home/shumengya/桌面/Python/InfoGenie/backend -python3 app.py diff --git a/start_frontend.bat b/start_frontend.bat deleted file mode 100755 index 556d2016..00000000 --- a/start_frontend.bat +++ /dev/null @@ -1,3 +0,0 @@ -@echo off -cd /d "e:\Python\InfoGenie\frontend" -npm start diff --git a/start_frontend.sh b/start_frontend.sh deleted file mode 100755 index 99ac201d..00000000 --- a/start_frontend.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -cd /home/shumengya/桌面/Python/InfoGenie/frontend -npm start diff --git a/用户数据模板.json b/用户数据模板.json deleted file mode 100755 index 764b3c75..00000000 --- a/用户数据模板.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "账号":"3205788256", - "邮箱":"3205788256@qq.com", - "密码":"0123456789" -} \ No newline at end of file