diff --git a/api/app.py b/api/app.py new file mode 100644 index 0000000..4f38f4f --- /dev/null +++ b/api/app.py @@ -0,0 +1,210 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +古诗词智能查询与解析器 - 后端API +简化版本,包含核心功能 +""" + +import os +import json +import logging +from datetime import datetime +from flask import Flask, request, jsonify +from flask_cors import CORS +import requests + +# 配置日志 +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +# 创建Flask应用 +app = Flask(__name__) +CORS(app) + +# 配置 +app.config['JSON_AS_ASCII'] = False + +# AI API配置 +SK_API_KEY = "sk-fdf7cc1c73504e628ec0119b7e11b8cc" +AI_API_URL = "https://api.deepseek.com/v1/chat/completions" + +# 示例诗词数据库 +SAMPLE_POETRY_DB = [ + { + "id": 1, + "title": "静夜思", + "author": "李白", + "dynasty": "唐", + "content": "床前明月光,疑是地上霜。\n举头望明月,低头思故乡。", + "type": "抒情", + "word_count": "五言", + "tags": ["思乡", "月亮", "夜晚"] + }, + { + "id": 2, + "title": "春晓", + "author": "孟浩然", + "dynasty": "唐", + "content": "春眠不觉晓,处处闻啼鸟。\n夜来风雨声,花落知多少。", + "type": "山水", + "word_count": "五言", + "tags": ["春天", "自然", "风景"] + }, + { + "id": 3, + "title": "水调歌头·明月几时有", + "author": "苏轼", + "dynasty": "宋", + "content": "明月几时有?把酒问青天。\n不知天上宫阙,今夕是何年。\n我欲乘风归去,又恐琼楼玉宇,高处不胜寒。\n起舞弄清影,何似在人间。", + "type": "抒情", + "word_count": "词", + "tags": ["中秋", "月亮", "思念"] + } +] + +def generate_ai_analysis(poetry_title, author, dynasty, purpose, usage, target_audience, depth, focus): + """生成AI解析""" + try: + system_prompt = f"""你是一位古典文学专家,精通古诗词解析。 +背景:诗词用于{usage},读者是{target_audience},解析深度为{depth},关注{focus}。 +要求:提供准确原文、详细注释、深入解读、学习建议。""" + + user_prompt = f"""解析以下诗词: +标题:{poetry_title} +作者:{author} +朝代:{dynasty} +目的:{purpose}""" + + messages = [ + {"role": "system", "content": system_prompt}, + {"role": "user", "content": user_prompt} + ] + + headers = { + "Content-Type": "application/json", + "Authorization": f"Bearer {SK_API_KEY}" + } + + data = { + "model": "deepseek-chat", + "messages": messages, + "temperature": 0.7, + "max_tokens": 1500 + } + + response = requests.post(AI_API_URL, headers=headers, json=data, timeout=30) + response.raise_for_status() + + return response.json()["choices"][0]["message"]["content"] + + except Exception as e: + logger.error(f"AI解析失败: {e}") + return f"AI解析生成失败: {str(e)}" + +# API路由 +@app.route('/') +def index(): + return jsonify({ + "name": "古诗词智能解析器API", + "version": "1.0.0", + "endpoints": ["/api/poetry", "/api/search", "/api/ai/analyze"] + }) + +@app.route('/api/poetry', methods=['GET']) +def get_poetry(): + """获取诗词列表""" + try: + return jsonify({ + "success": True, + "data": SAMPLE_POETRY_DB, + "count": len(SAMPLE_POETRY_DB) + }) + except Exception as e: + return jsonify({"success": False, "error": str(e)}), 500 + +@app.route('/api/search', methods=['GET']) +def search(): + """搜索诗词""" + try: + query = request.args.get('q', '').lower() + if not query: + return jsonify({"success": True, "data": SAMPLE_POETRY_DB}) + + results = [] + for poetry in SAMPLE_POETRY_DB: + if (query in poetry['title'].lower() or + query in poetry['author'].lower() or + query in poetry['content'].lower()): + results.append(poetry) + + return jsonify({ + "success": True, + "data": results, + "count": len(results) + }) + except Exception as e: + return jsonify({"success": False, "error": str(e)}), 500 + +@app.route('/api/ai/analyze', methods=['POST']) +def analyze(): + """AI解析诗词""" + try: + data = request.get_json() + + # 必要参数检查 + required = ['poetry_title', 'author', 'dynasty'] + for field in required: + if field not in data: + return jsonify({ + "success": False, + "error": f"缺少参数: {field}" + }), 400 + + # 获取参数 + poetry_title = data['poetry_title'] + author = data['author'] + dynasty = data['dynasty'] + purpose = data.get('purpose', '学习理解') + usage = data.get('usage', '课堂教学') + target_audience = data.get('target_audience', '中小学生') + depth = data.get('depth', '基础') + focus = data.get('focus', '综合解析') + + # 生成解析 + analysis = generate_ai_analysis( + poetry_title, author, dynasty, purpose, usage, + target_audience, depth, focus + ) + + return jsonify({ + "success": True, + "data": { + "analysis": analysis, + "metadata": { + "poetry_title": poetry_title, + "author": author, + "dynasty": dynasty, + "timestamp": datetime.now().isoformat() + } + } + }) + + except Exception as e: + logger.error(f"解析失败: {e}") + return jsonify({"success": False, "error": str(e)}), 500 + +@app.route('/api/poetry/', methods=['GET']) +def get_poetry_detail(poetry_id): + """获取诗词详情""" + try: + poetry = next((p for p in SAMPLE_POETRY_DB if p['id'] == poetry_id), None) + if not poetry: + return jsonify({"success": False, "error": "诗词未找到"}), 404 + + return jsonify({"success": True, "data": poetry}) + except Exception as e: + return jsonify({"success": False, "error": str(e)}), 500 + +if __name__ == '__main__': + logger.info("启动古诗词智能解析器API服务器...") + app.run(host='0.0.0.0', port=5000, debug=True) diff --git a/index.html b/index.html new file mode 100644 index 0000000..b84fc0a --- /dev/null +++ b/index.html @@ -0,0 +1,322 @@ + + + + + + 古诗词智能查询与解析器 + + + + + + + + + + + +
+ +
+
+

探索千年诗词之美

+

AI智能解析,深度理解古诗词的意境与内涵

+ +
+ 快速筛选: + + + + +
+
+
+ + + + + +
+

AI深度解析

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

AI解析结果将显示在这里

+

选择诗词并设置解析参数后,点击"生成AI解析"按钮

+
+
+
+
+ + +
+

诗词浏览

+
+
+ + +
+
+ +
+
+
+ +
+
+ 加载中... +
+
+ + +
+

交互学习

+
+
+
+ +
+

对比分析

+

比较两首诗词的异同,深入理解不同风格

+ +
+
+
+ +
+

相似推荐

+

基于当前诗词推荐主题、风格相似的作品

+ +
+
+
+ +
+

知识问答

+

AI问答功能,解答关于诗词的各类问题

+ +
+
+
+ +
+

背诵助手

+

填空测试、顺序排序等背诵辅助功能

+ +
+
+
+
+ + + + + + + + + + + + diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..d309df8 --- /dev/null +++ b/manifest.json @@ -0,0 +1,127 @@ +{ + "name": "古诗词智能解析器", + "short_name": "诗词解析", + "description": "AI智能查询与解析古诗词,提供深度文学分析和学习功能", + "start_url": "/", + "display": "standalone", + "background_color": "#fffaf0", + "theme_color": "#8b4513", + "orientation": "portrait-primary", + "icons": [ + { + "src": "/static/images/icon-72.png", + "sizes": "72x72", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/static/images/icon-96.png", + "sizes": "96x96", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/static/images/icon-128.png", + "sizes": "128x128", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/static/images/icon-144.png", + "sizes": "144x144", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/static/images/icon-152.png", + "sizes": "152x152", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/static/images/icon-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/static/images/icon-384.png", + "sizes": "384x384", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/static/images/icon-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "any maskable" + } + ], + "screenshots": [ + { + "src": "/static/images/screenshot1.png", + "sizes": "1280x720", + "type": "image/png", + "form_factor": "wide", + "label": "古诗词智能解析器主界面" + }, + { + "src": "/static/images/screenshot2.png", + "sizes": "750x1334", + "type": "image/png", + "form_factor": "narrow", + "label": "移动端诗词浏览界面" + } + ], + "categories": ["education", "books", "lifestyle"], + "lang": "zh-CN", + "dir": "ltr", + "prefer_related_applications": false, + "related_applications": [], + "scope": "/", + "shortcuts": [ + { + "name": "智能搜索", + "short_name": "搜索", + "description": "快速搜索古诗词", + "url": "/#search", + "icons": [ + { + "src": "/static/images/search-icon.png", + "sizes": "96x96" + } + ] + }, + { + "name": "AI解析", + "short_name": "解析", + "description": "使用AI深度解析诗词", + "url": "/#ai-analysis", + "icons": [ + { + "src": "/static/images/ai-icon.png", + "sizes": "96x96" + } + ] + }, + { + "name": "我的收藏", + "short_name": "收藏", + "description": "查看收藏的诗词", + "url": "/#personal", + "icons": [ + { + "src": "/static/images/favorite-icon.png", + "sizes": "96x96" + } + ] + } + ], + "features": [ + "古诗词查询", + "AI智能解析", + "离线阅读", + "诗词收藏", + "学习记录" + ] +} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..727b380 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +Flask==2.3.3 +Flask-CORS==4.0.0 +requests==2.31.0 +python-dotenv==1.0.0 diff --git a/run.py b/run.py new file mode 100644 index 0000000..121931d --- /dev/null +++ b/run.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +古诗词智能查询与解析器 - 启动脚本 +""" + +import os +import sys +import subprocess +import time +import webbrowser + +def install_dependencies(): + """安装Python依赖""" + print("1. 安装Python依赖...") + try: + subprocess.check_call([sys.executable, "-m", "pip", "install", "-r", "requirements.txt"]) + print("依赖安装成功!") + return True + except subprocess.CalledProcessError as e: + print(f"依赖安装失败: {e}") + return False + +def start_backend(): + """启动后端API服务器""" + print("2. 启动后端API服务器...") + backend_cmd = [sys.executable, "api/app.py"] + + # 在Windows上使用CREATE_NEW_CONSOLE标志 + if sys.platform == "win32": + subprocess.Popen(backend_cmd, cwd=os.getcwd(), + creationflags=subprocess.CREATE_NEW_CONSOLE) + else: + subprocess.Popen(backend_cmd, cwd=os.getcwd()) + + print("后端服务器启动中...") + time.sleep(3) + return True + +def start_frontend(): + """启动前端HTTP服务器""" + print("3. 启动前端HTTP服务器...") + frontend_cmd = [sys.executable, "-m", "http.server", "8000"] + + if sys.platform == "win32": + subprocess.Popen(frontend_cmd, cwd=os.getcwd(), + creationflags=subprocess.CREATE_NEW_CONSOLE) + else: + subprocess.Popen(frontend_cmd, cwd=os.getcwd()) + + print("前端服务器启动中...") + time.sleep(2) + return True + +def open_browser(): + """打开浏览器""" + print("4. 打开浏览器访问应用...") + url = "http://localhost:8000" + webbrowser.open(url) + print(f"已打开浏览器访问: {url}") + return True + +def main(): + """主函数""" + print("=" * 50) + print("古诗词智能查询与解析器 - 启动程序") + print("=" * 50) + + # 检查当前目录 + if not os.path.exists("api/app.py"): + print("错误: 请在项目根目录运行此脚本") + return + + # 安装依赖 + if not install_dependencies(): + print("警告: 依赖安装失败,尝试继续运行...") + + # 启动后端 + if not start_backend(): + print("错误: 后端启动失败") + return + + # 启动前端 + if not start_frontend(): + print("错误: 前端启动失败") + return + + # 打开浏览器 + if not open_browser(): + print("警告: 无法自动打开浏览器") + + print("\n" + "=" * 50) + print("应用启动完成!") + print("后端API: http://localhost:5000") + print("前端应用: http://localhost:8000") + print("\n按Ctrl+C停止所有服务器") + print("=" * 50) + + try: + # 保持脚本运行 + while True: + time.sleep(1) + except KeyboardInterrupt: + print("\n正在停止服务器...") + +if __name__ == "__main__": + main() diff --git a/start_app.bat b/start_app.bat new file mode 100644 index 0000000..d59e885 --- /dev/null +++ b/start_app.bat @@ -0,0 +1,28 @@ +@echo off +echo 正在启动古诗词智能查询与解析器... +echo. + +echo 1. 安装Python依赖... +pip install -r requirements.txt + +echo. +echo 2. 启动后端API服务器... +start cmd /k "cd /d %~dp0api && python app.py" + +echo. +echo 3. 启动前端HTTP服务器... +timeout /t 3 /nobreak > nul +start cmd /k "cd /d %~dp0 && python -m http.server 8000" + +echo. +echo 4. 打开浏览器访问应用... +timeout /t 5 /nobreak > nul +start http://localhost:8000 + +echo. +echo 应用已启动! +echo 后端API: http://localhost:5000 +echo 前端应用: http://localhost:8000 +echo. +echo 按任意键退出... +pause > nul diff --git a/static/css/style.css b/static/css/style.css new file mode 100644 index 0000000..5a7b1f7 --- /dev/null +++ b/static/css/style.css @@ -0,0 +1,708 @@ +/* 基础样式 */ +:root { + --primary-color: #8b4513; + --secondary-color: #d2691e; + --accent-color: #a0522d; + --light-color: #f5f5dc; + --dark-color: #2c1810; + --text-color: #333; + --text-light: #666; + --bg-color: #fffaf0; + --card-bg: #fff; + --shadow: 0 4px 12px rgba(139, 69, 19, 0.1); + --border-radius: 12px; + --transition: all 0.3s ease; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Noto Serif SC', serif; + line-height: 1.6; + color: var(--text-color); + background-color: var(--bg-color); + background-image: url('../images/pattern.png'); + background-size: 300px; + background-blend-mode: overlay; + background-color: rgba(255, 250, 240, 0.9); +} + +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 20px; +} + +/* 导航栏 */ +.navbar { + background-color: var(--primary-color); + color: white; + padding: 1rem 0; + position: sticky; + top: 0; + z-index: 1000; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); +} + +.navbar .container { + display: flex; + justify-content: space-between; + align-items: center; +} + +.logo { + display: flex; + align-items: center; + gap: 10px; +} + +.logo i { + font-size: 2rem; + color: var(--light-color); +} + +.logo h1 { + font-family: 'Ma Shan Zheng', cursive; + font-size: 1.8rem; + font-weight: normal; +} + +.nav-links { + display: flex; + gap: 2rem; +} + +.nav-links a { + color: white; + text-decoration: none; + display: flex; + align-items: center; + gap: 5px; + padding: 0.5rem 1rem; + border-radius: var(--border-radius); + transition: var(--transition); +} + +.nav-links a:hover, +.nav-links a.active { + background-color: var(--secondary-color); + transform: translateY(-2px); +} + +.menu-toggle { + display: none; + background: none; + border: none; + color: white; + font-size: 1.5rem; + cursor: pointer; +} + +/* 首页横幅 */ +.hero { + background: linear-gradient(135deg, var(--primary-color), var(--accent-color)); + color: white; + padding: 4rem 0; + text-align: center; + border-radius: 0 0 var(--border-radius) var(--border-radius); + margin-bottom: 3rem; + position: relative; + overflow: hidden; +} + +.hero::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: url('../images/hero-pattern.png'); + opacity: 0.1; +} + +.hero-content { + position: relative; + z-index: 1; +} + +.hero h2 { + font-family: 'Ma Shan Zheng', cursive; + font-size: 3rem; + margin-bottom: 1rem; +} + +.hero p { + font-size: 1.2rem; + margin-bottom: 2rem; + opacity: 0.9; +} + +.search-box { + max-width: 600px; + margin: 0 auto 2rem; + display: flex; + gap: 10px; +} + +.search-box input { + flex: 1; + padding: 1rem; + border: none; + border-radius: var(--border-radius); + font-size: 1rem; + font-family: 'Noto Serif SC', serif; +} + +.search-box button { + padding: 1rem 2rem; + background-color: var(--secondary-color); + color: white; + border: none; + border-radius: var(--border-radius); + cursor: pointer; + font-size: 1rem; + display: flex; + align-items: center; + gap: 8px; + transition: var(--transition); +} + +.search-box button:hover { + background-color: var(--accent-color); + transform: translateY(-2px); +} + +.quick-filters { + display: flex; + justify-content: center; + align-items: center; + gap: 1rem; + flex-wrap: wrap; +} + +.quick-filters span { + font-size: 1rem; +} + +.filter-btn { + padding: 0.5rem 1.5rem; + background-color: rgba(255, 255, 255, 0.2); + color: white; + border: 1px solid rgba(255, 255, 255, 0.3); + border-radius: 20px; + cursor: pointer; + transition: var(--transition); +} + +.filter-btn:hover { + background-color: rgba(255, 255, 255, 0.3); + transform: translateY(-2px); +} + +/* 内容区块 */ +.section { + margin-bottom: 4rem; + padding: 2rem; + background-color: var(--card-bg); + border-radius: var(--border-radius); + box-shadow: var(--shadow); +} + +.section h2 { + color: var(--primary-color); + margin-bottom: 2rem; + padding-bottom: 1rem; + border-bottom: 2px solid var(--light-color); + display: flex; + align-items: center; + gap: 10px; +} + +/* 搜索面板 */ +.search-panel { + background-color: var(--light-color); + padding: 2rem; + border-radius: var(--border-radius); +} + +.search-form { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 1.5rem; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.form-group label { + color: var(--primary-color); + font-weight: bold; + display: flex; + align-items: center; + gap: 5px; +} + +.form-group input, +.form-group select { + padding: 0.8rem; + border: 1px solid #ddd; + border-radius: var(--border-radius); + font-family: 'Noto Serif SC', serif; + font-size: 1rem; + transition: var(--transition); +} + +.form-group input:focus, +.form-group select:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 2px rgba(139, 69, 19, 0.2); +} + +/* 按钮样式 */ +.btn-primary, +.btn-secondary { + padding: 1rem 2rem; + border: none; + border-radius: var(--border-radius); + cursor: pointer; + font-size: 1rem; + font-family: 'Noto Serif SC', serif; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + transition: var(--transition); +} + +.btn-primary { + background-color: var(--primary-color); + color: white; +} + +.btn-primary:hover { + background-color: var(--secondary-color); + transform: translateY(-2px); +} + +.btn-secondary { + background-color: var(--light-color); + color: var(--primary-color); + border: 1px solid var(--primary-color); +} + +.btn-secondary:hover { + background-color: var(--primary-color); + color: white; + transform: translateY(-2px); +} + +/* AI解析面板 */ +.ai-analysis-panel { + display: grid; + grid-template-columns: 1fr 2fr; + gap: 2rem; +} + +.analysis-controls { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + +.analysis-result { + background-color: var(--light-color); + border-radius: var(--border-radius); + padding: 2rem; + min-height: 400px; + overflow-y: auto; +} + +.result-placeholder { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + color: var(--text-light); + text-align: center; +} + +.result-placeholder i { + font-size: 4rem; + margin-bottom: 1rem; + color: var(--primary-color); + opacity: 0.5; +} + +/* 诗词网格 */ +.browse-controls { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 2rem; +} + +.view-toggle { + display: flex; + gap: 10px; +} + +.view-btn { + padding: 0.5rem 1rem; + background-color: var(--light-color); + border: 1px solid #ddd; + border-radius: var(--border-radius); + cursor: pointer; + display: flex; + align-items: center; + gap: 5px; +} + +.view-btn.active { + background-color: var(--primary-color); + color: white; + border-color: var(--primary-color); +} + +.poetry-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + gap: 2rem; +} + +.poetry-card { + background-color: var(--card-bg); + border-radius: var(--border-radius); + overflow: hidden; + box-shadow: var(--shadow); + transition: var(--transition); + cursor: pointer; +} + +.poetry-card:hover { + transform: translateY(-5px); + box-shadow: 0 8px 20px rgba(139, 69, 19, 0.2); +} + +.poetry-card-header { + background-color: var(--primary-color); + color: white; + padding: 1.5rem; +} + +.poetry-card-header h3 { + font-size: 1.3rem; + margin-bottom: 0.5rem; +} + +.poetry-card-header .meta { + display: flex; + justify-content: space-between; + font-size: 0.9rem; + opacity: 0.9; +} + +.poetry-card-body { + padding: 1.5rem; +} + +.poetry-content { + font-size: 1.1rem; + line-height: 1.8; + margin-bottom: 1rem; + font-family: 'Ma Shan Zheng', cursive; +} + +.poetry-tags { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; +} + +.tag { + background-color: var(--light-color); + color: var(--primary-color); + padding: 0.3rem 0.8rem; + border-radius: 15px; + font-size: 0.8rem; +} + +.loading { + text-align: center; + padding: 2rem; + color: var(--text-light); +} + +.loading i { + margin-right: 10px; +} + +/* 学习功能 */ +.learning-features { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 2rem; +} + +.feature-card { + background-color: var(--card-bg); + padding: 2rem; + border-radius: var(--border-radius); + text-align: center; + box-shadow: var(--shadow); + transition: var(--transition); +} + +.feature-card:hover { + transform: translateY(-5px); + box-shadow: 0 8px 20px rgba(139, 69, 19, 0.2); +} + +.feature-icon { + font-size: 3rem; + color: var(--primary-color); + margin-bottom: 1rem; +} + +.feature-card h3 { + margin-bottom: 1rem; + color: var(--primary-color); +} + +.feature-card p { + color: var(--text-light); + margin-bottom: 1.5rem; +} + +/* 页脚 */ +footer { + background-color: var(--dark-color); + color: white; + padding: 3rem 0 1rem; + margin-top: 4rem; +} + +.footer-content { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 2rem; + margin-bottom: 2rem; +} + +.footer-section h3, +.footer-section h4 { + color: var(--light-color); + margin-bottom: 1rem; +} + +.footer-section a { + color: #ccc; + text-decoration: none; + display: block; + margin-bottom: 0.5rem; + transition: var(--transition); +} + +.footer-section a:hover { + color: white; + transform: translateX(5px); +} + +.social-links { + display: flex; + gap: 1rem; +} + +.social-links a { + font-size: 1.5rem; + color: #ccc; + transition: var(--transition); +} + +.social-links a:hover { + color: white; + transform: translateY(-3px); +} + +.footer-bottom { + text-align: center; + padding-top: 2rem; + border-top: 1px solid rgba(255, 255, 255, 0.1); + display: flex; + justify-content: space-between; + align-items: center; +} + +.pwa-badge { + background-color: var(--primary-color); + padding: 0.5rem 1rem; + border-radius: 20px; + display: inline-flex; + align-items: center; + gap: 5px; +} + +/* 模态框 */ +.modal { + display: none; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + z-index: 2000; + align-items: center; + justify-content: center; +} + +.modal.active { + display: flex; +} + +.modal-content { + background-color: var(--card-bg); + border-radius: var(--border-radius); + width: 90%; + max-width: 800px; + max-height: 90vh; + overflow: hidden; + display: flex; + flex-direction: column; +} + +.modal-header { + background-color: var(--primary-color); + color: white; + padding: 1.5rem; + display: flex; + justify-content: space-between; + align-items: center; +} + +.close-modal { + background: none; + border: none; + color: white; + font-size: 2rem; + cursor: pointer; + line-height: 1; +} + +.modal-body { + padding: 2rem; + overflow-y: auto; + flex: 1; +} + +.modal-footer { + padding: 1.5rem; + background-color: var(--light-color); + display: flex; + justify-content: flex-end; + gap: 1rem; +} + +/* 响应式设计 */ +@media (max-width: 768px) { + .navbar .container { + flex-wrap: wrap; + } + + .nav-links { + display: none; + width: 100%; + flex-direction: column; + margin-top: 1rem; + } + + .nav-links.active { + display: flex; + } + + .menu-toggle { + display: block; + } + + .hero h2 { + font-size: 2rem; + } + + .search-box { + flex-direction: column; + } + + .ai-analysis-panel { + grid-template-columns: 1fr; + } + + .poetry-grid { + grid-template-columns: 1fr; + } + + .footer-bottom { + flex-direction: column; + gap: 1rem; + } +} + +@media (max-width: 480px) { + .container { + padding: 0 10px; + } + + .section { + padding: 1rem; + } + + .search-form { + grid-template-columns: 1fr; + } + + .learning-features { + grid-template-columns: 1fr; + } +} + +/* 动画 */ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.fade-in { + animation: fadeIn 0.5s ease forwards; +} + +/* 滚动条样式 */ +::-webkit-scrollbar { + width: 8px; +} + +::-webkit-scrollbar-track { + background: var(--light-color); +} + +::-webkit-scrollbar-thumb { + background: var(--primary-color); + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--secondary-color); +} diff --git a/static/js/main.js b/static/js/main.js new file mode 100644 index 0000000..21fb245 --- /dev/null +++ b/static/js/main.js @@ -0,0 +1,745 @@ +// 古诗词智能查询与解析器 - 主JavaScript文件 + +document.addEventListener('DOMContentLoaded', function() { + // 初始化应用 + initApp(); + + // 加载示例诗词数据 + loadSamplePoetryData(); + + // 设置事件监听器 + setupEventListeners(); +}); + +// 应用初始化 +function initApp() { + console.log('古诗词智能解析器应用已启动'); + + // 设置当前年份 + document.querySelector('.footer-bottom p').innerHTML = + `© ${new Date().getFullYear()} 古诗词智能解析器 | 基于H5技术开发 | PWA支持`; + + // 初始化导航栏 + initNavigation(); + + // 初始化模态框 + initModal(); + + // 检查PWA支持 + checkPWASupport(); +} + +// 初始化导航栏 +function initNavigation() { + const menuToggle = document.getElementById('menuToggle'); + const navLinks = document.querySelector('.nav-links'); + + if (menuToggle) { + menuToggle.addEventListener('click', function() { + navLinks.classList.toggle('active'); + }); + } + + // 平滑滚动到锚点 + document.querySelectorAll('a[href^="#"]').forEach(anchor => { + anchor.addEventListener('click', function(e) { + e.preventDefault(); + + const targetId = this.getAttribute('href'); + if (targetId === '#') return; + + const targetElement = document.querySelector(targetId); + if (targetElement) { + // 关闭移动端菜单 + navLinks.classList.remove('active'); + + // 平滑滚动 + window.scrollTo({ + top: targetElement.offsetTop - 80, + behavior: 'smooth' + }); + + // 更新活动链接 + document.querySelectorAll('.nav-links a').forEach(link => { + link.classList.remove('active'); + }); + this.classList.add('active'); + } + }); + }); +} + +// 初始化模态框 +function initModal() { + const modal = document.getElementById('poetryDetailModal'); + const closeModalBtn = document.querySelector('.close-modal'); + + if (closeModalBtn) { + closeModalBtn.addEventListener('click', function() { + modal.classList.remove('active'); + }); + } + + // 点击模态框外部关闭 + modal.addEventListener('click', function(e) { + if (e.target === modal) { + modal.classList.remove('active'); + } + }); + + // ESC键关闭模态框 + document.addEventListener('keydown', function(e) { + if (e.key === 'Escape' && modal.classList.contains('active')) { + modal.classList.remove('active'); + } + }); +} + +// 检查PWA支持 +function checkPWASupport() { + if ('serviceWorker' in navigator) { + console.log('支持Service Worker,PWA功能可用'); + + // 注册Service Worker + navigator.serviceWorker.register('/static/js/service-worker.js') + .then(registration => { + console.log('Service Worker 注册成功:', registration); + }) + .catch(error => { + console.log('Service Worker 注册失败:', error); + }); + } +} + +// 加载示例诗词数据 +function loadSamplePoetryData() { + const samplePoetry = [ + { + id: 1, + title: "静夜思", + author: "李白", + dynasty: "唐", + content: "床前明月光,疑是地上霜。\n举头望明月,低头思故乡。", + type: "抒情", + wordCount: "五言", + tags: ["思乡", "月亮", "夜晚"], + popularity: 95 + }, + { + id: 2, + title: "春晓", + author: "孟浩然", + dynasty: "唐", + content: "春眠不觉晓,处处闻啼鸟。\n夜来风雨声,花落知多少。", + type: "山水", + wordCount: "五言", + tags: ["春天", "自然", "风景"], + popularity: 88 + }, + { + id: 3, + title: "水调歌头·明月几时有", + author: "苏轼", + dynasty: "宋", + content: "明月几时有?把酒问青天。\n不知天上宫阙,今夕是何年。\n我欲乘风归去,又恐琼楼玉宇,高处不胜寒。\n起舞弄清影,何似在人间。", + type: "抒情", + wordCount: "词", + tags: ["中秋", "月亮", "思念"], + popularity: 92 + }, + { + id: 4, + title: "登鹳雀楼", + author: "王之涣", + dynasty: "唐", + content: "白日依山尽,黄河入海流。\n欲穷千里目,更上一层楼。", + type: "哲理", + wordCount: "五言", + tags: ["登高", "哲理", "壮丽"], + popularity: 85 + }, + { + id: 5, + title: "望庐山瀑布", + author: "李白", + dynasty: "唐", + content: "日照香炉生紫烟,遥看瀑布挂前川。\n飞流直下三千尺,疑是银河落九天。", + type: "山水", + wordCount: "七言", + tags: ["瀑布", "自然", "壮丽"], + popularity: 90 + }, + { + id: 6, + title: "江雪", + author: "柳宗元", + dynasty: "唐", + content: "千山鸟飞绝,万径人踪灭。\n孤舟蓑笠翁,独钓寒江雪。", + type: "山水", + wordCount: "五言", + tags: ["冬天", "孤独", "自然"], + popularity: 87 + } + ]; + + // 渲染诗词卡片 + renderPoetryCards(samplePoetry); +} + +// 渲染诗词卡片 +function renderPoetryCards(poetryList) { + const poetryGrid = document.getElementById('poetryGrid'); + if (!poetryGrid) return; + + poetryGrid.innerHTML = ''; + + poetryList.forEach(poetry => { + const card = createPoetryCard(poetry); + poetryGrid.appendChild(card); + }); + + // 隐藏加载指示器 + const loadingIndicator = document.getElementById('loadingIndicator'); + if (loadingIndicator) { + loadingIndicator.style.display = 'none'; + } +} + +// 创建诗词卡片 +function createPoetryCard(poetry) { + const card = document.createElement('div'); + card.className = 'poetry-card fade-in'; + card.dataset.id = poetry.id; + + card.innerHTML = ` +
+

${poetry.title}

+
+ ${poetry.author} + ${poetry.dynasty} +
+
+
+
${poetry.content.replace(/\n/g, '
')}
+
+ ${poetry.tags.map(tag => `${tag}`).join('')} +
+
+ `; + + // 添加点击事件 + card.addEventListener('click', function() { + showPoetryDetail(poetry); + }); + + return card; +} + +// 显示诗词详情 +function showPoetryDetail(poetry) { + const modal = document.getElementById('poetryDetailModal'); + const modalTitle = document.getElementById('modalTitle'); + const modalBody = document.getElementById('modalBody'); + + if (!modal || !modalTitle || !modalBody) return; + + modalTitle.textContent = poetry.title; + + modalBody.innerHTML = ` +
+
+

${poetry.title}

+
+ ${poetry.author} + ${poetry.dynasty} + ${poetry.type} + ${poetry.wordCount} +
+
+
+
原文:
+
${poetry.content}
+
现代汉语翻译:
+

${getTranslation(poetry)}

+
简要赏析:
+

${getBriefAnalysis(poetry)}

+
+
+
标签:
+
+ ${poetry.tags.map(tag => `${tag}`).join('')} +
+
+
+ `; + + // 更新按钮事件 + const favoriteBtn = document.getElementById('favoriteBtn'); + const analyzeBtn = document.getElementById('analyzeBtn'); + const shareBtn = document.getElementById('shareBtn'); + + if (favoriteBtn) { + favoriteBtn.onclick = function() { + toggleFavorite(poetry.id); + }; + } + + if (analyzeBtn) { + analyzeBtn.onclick = function() { + startAIAnalysis(poetry); + }; + } + + if (shareBtn) { + shareBtn.onclick = function() { + sharePoetry(poetry); + }; + } + + // 显示模态框 + modal.classList.add('active'); +} + +// 获取翻译(示例) +function getTranslation(poetry) { + const translations = { + 1: "明亮的月光洒在床前,好像地上泛起了一层白霜。\n我抬起头来,看那窗外天空中的明月,不由得低头沉思,想起远方的家乡。", + 2: "春日里贪睡不知不觉天已破晓,搅乱我酣眠的是那啁啾的小鸟。\n昨天夜里风声雨声一直不断,那娇美的春花不知被吹落了多少?", + 3: "明月从什么时候才开始出现的?我端起酒杯遥问苍天。\n不知道在天上的宫殿,今天晚上是何年何月。\n我想要乘御清风回到天上,又恐怕在美玉砌成的楼宇,受不住高耸九天的寒冷。\n翩翩起舞玩赏着月下清影,哪像是在人间。", + 4: "夕阳依傍着西山慢慢地沉没,滔滔黄河朝着东海汹涌奔流。\n若想把千里的风光景物看够,那就要登上更高的一层城楼。", + 5: "香炉峰在阳光的照射下生起紫色烟霞,从远处看去瀑布好似白色绢绸悬挂山前。\n高崖上飞腾直落的瀑布好像有几千尺,让人怀疑是银河从天上泻落到人间。", + 6: "所有的山上,飞鸟的身影已经绝迹,所有道路都不见人的踪迹。\n江面孤舟上,一位披戴着蓑笠的老翁,独自在漫天风雪中垂钓。" + }; + + return translations[poetry.id] || "翻译加载中..."; +} + +// 获取简要赏析(示例) +function getBriefAnalysis(poetry) { + const analyses = { + 1: "这首诗写的是在寂静的月夜思念家乡的感受。诗的前两句,是写诗人在作客他乡的特定环境中一刹那间所产生的错觉。后两句通过动作神态的刻画,深化思乡之情。", + 2: "这首诗是唐代诗人孟浩然隐居鹿门山时所作。诗人抓住春天的早晨刚刚醒来时的一瞬间展开联想,描绘了一幅春天早晨绚丽的图景,抒发了诗人热爱春天、珍惜春光的美好心情。", + 3: "此词是中秋望月怀人之作,表达了对胞弟苏辙的无限怀念。词人运用形象描绘手法,勾勒出一种皓月当空、亲人千里、孤高旷远的境界氛围,反衬自己遗世独立的意绪和往昔的神话传说融合一处,在月的阴晴圆缺当中,渗进浓厚的哲学意味。", + 4: "这首诗写诗人在登高望远中表现出来的不凡的胸襟抱负,反映了盛唐时期人们积极向上的进取精神。前两句写所见,后两句写所感,把哲理与景物、情势溶化得天衣无缝。", + 5: "这首诗形象地描绘了庐山瀑布雄奇壮丽的景色,反映了诗人对祖国大好河山的无限热爱。诗人用夸张的比喻和浪漫的想象,把瀑布的气势写得出神入化,给人以美的享受。", + 6: "这首诗描绘了一幅江乡雪景图。山山是雪,路路皆白。飞鸟绝迹,人踪湮没。遐景苍茫,迩景孤冷。意境幽僻,情调凄寂。渔翁形象,精雕细琢,清晰明朗,完整突出。" + }; + + return analyses[poetry.id] || "赏析加载中..."; +} + +// 设置事件监听器 +function setupEventListeners() { + // 快速搜索按钮 + const quickSearchBtn = document.getElementById('quickSearchBtn'); + if (quickSearchBtn) { + quickSearchBtn.addEventListener('click', performQuickSearch); + } + + // 快速搜索输入框回车键 + const quickSearchInput = document.getElementById('quickSearch'); + if (quickSearchInput) { + quickSearchInput.addEventListener('keypress', function(e) { + if (e.key === 'Enter') { + performQuickSearch(); + } + }); + } + + // 高级搜索按钮 + const advancedSearchBtn = document.getElementById('advancedSearchBtn'); + if (advancedSearchBtn) { + advancedSearchBtn.addEventListener('click', performAdvancedSearch); + } + + // 重置搜索按钮 + const resetSearchBtn = document.getElementById('resetSearchBtn'); + if (resetSearchBtn) { + resetSearchBtn.addEventListener('click', resetSearch); + } + + // 生成AI解析按钮 + const generateAnalysisBtn = document.getElementById('generateAnalysisBtn'); + if (generateAnalysisBtn) { + generateAnalysisBtn.addEventListener('click', generateAIAnalysis); + } + + // 快速筛选按钮 + document.querySelectorAll('.filter-btn').forEach(btn => { + btn.addEventListener('click', function() { + const dynasty = this.dataset.dynasty; + const type = this.dataset.type; + filterPoetry(dynasty, type); + }); + }); + + // 视图切换按钮 + document.querySelectorAll('.view-btn').forEach(btn => { + btn.addEventListener('click', function() { + const view = this.dataset.view; + switchView(view); + }); + }); + + // 排序选择 + const sortBySelect = document.getElementById('sortBy'); + if (sortBySelect) { + sortBySelect.addEventListener('change', function() { + sortPoetry(this.value); + }); + } + + // 学习功能按钮 + document.getElementById('compareBtn')?.addEventListener('click', startComparison); + document.getElementById('recommendBtn')?.addEventListener('click', getRecommendations); + document.getElementById('qaBtn')?.addEventListener('click', startQA); + document.getElementById('memorizeBtn')?.addEventListener('click', startMemorization); +} + +// 执行快速搜索 +function performQuickSearch() { + const query = document.getElementById('quickSearch').value.trim(); + + if (!query) { + alert('请输入搜索内容'); + return; + } + + showLoading(true); + + // 模拟API调用 + setTimeout(() => { + // 这里应该是实际的API调用 + console.log('执行快速搜索:', query); + + // 显示搜索结果 + showSearchResults(query); + showLoading(false); + }, 1000); +} + +// 执行高级搜索 +function performAdvancedSearch() { + const title = document.getElementById('poetryTitle').value.trim(); + const author = document.getElementById('author').value.trim(); + const dynasty = document.getElementById('dynasty').value; + const keywords = document.getElementById('keywords').value.trim(); + const poetryType = document.getElementById('poetryType').value; + const wordCount = document.getElementById('wordCount').value; + + // 构建搜索条件 + const searchCriteria = { + title, + author, + dynasty, + keywords, + poetryType, + wordCount + }; + + console.log('高级搜索条件:', searchCriteria); + + showLoading(true); + + // 模拟API调用 + setTimeout(() => { + // 这里应该是实际的API调用 + showSearchResults('高级搜索'); + showLoading(false); + }, 1500); +} + +// 重置搜索 +function resetSearch() { + document.getElementById('poetryTitle').value = ''; + document.getElementById('author').value = ''; + document.getElementById('dynasty').value = ''; + document.getElementById('keywords').value = ''; + document.getElementById('poetryType').value = ''; + document.getElementById('wordCount').value = ''; + + // 重新加载所有诗词 + loadSamplePoetryData(); +} + +// 显示搜索结果 +function showSearchResults(query) { + const analysisResult = document.getElementById('analysisResult'); + if (!analysisResult) return; + + analysisResult.innerHTML = ` +
+

搜索结果:${query}

+

找到 6 首相关诗词

+
+

1. 静夜思 - 李白 (唐代)

+

2. 春晓 - 孟浩然 (唐代)

+

3. 水调歌头·明月几时有 - 苏轼 (宋代)

+

4. 登鹳雀楼 - 王之涣 (唐代)

+

5. 望庐山瀑布 - 李白 (唐代)

+

6. 江雪 - 柳宗元 (唐代)

+
+

注:这是演示数据,实际应用中会连接到真实的诗词数据库和AI解析服务。

+
+ `; + + // 滚动到结果区域 + document.getElementById('ai-analysis').scrollIntoView({ behavior: 'smooth' }); +} + +// 显示/隐藏加载指示器 +function showLoading(show) { + const loadingIndicator = document.getElementById('loadingIndicator'); + if (loadingIndicator) { + loadingIndicator.style.display = show ? 'block' : 'none'; + } +} + +// 过滤诗词 +function filterPoetry(dynasty, type) { + showLoading(true); + + setTimeout(() => { + console.log(`过滤诗词: 朝代=${dynasty}, 类型=${type}`); + + // 这里应该是实际的过滤逻辑 + // 暂时重新加载所有数据 + loadSamplePoetryData(); + showLoading(false); + }, 800); +} + +// 切换视图 +function switchView(view) { + const poetryGrid = document.getElementById('poetryGrid'); + if (!poetryGrid) return; + + // 更新按钮状态 + document.querySelectorAll('.view-btn').forEach(btn => { + btn.classList.toggle('active', btn.dataset.view === view); + }); + + // 切换视图类 + poetryGrid.className = view === 'list' ? 'poetry-list' : 'poetry-grid'; + + console.log(`切换到${view === 'list' ? '列表' : '网格'}视图`); +} + +// 排序诗词 +function sortPoetry(sortBy) { + console.log(`按${sortBy}排序诗词`); + + // 这里应该是实际的排序逻辑 + // 暂时只是重新加载 + loadSamplePoetryData(); +} + +// 生成AI解析 +function generateAIAnalysis() { + const purpose = document.getElementById('purpose').value; + const usage = document.getElementById('usage').value; + const targetAudience = document.getElementById('targetAudience').value; + const depth = document.getElementById('depth').value; + const focus = document.getElementById('focus').value; + + // 获取当前选中的诗词(如果有) + const selectedPoetry = getSelectedPoetry(); + + if (!selectedPoetry) { + alert('请先选择一首诗词(点击诗词卡片)'); + return; + } + + showLoading(true); + + // 模拟AI解析生成 + setTimeout(() => { + const analysisResult = document.getElementById('analysisResult'); + if (!analysisResult) return; + + analysisResult.innerHTML = ` +
+

AI深度解析结果

+
+

${selectedPoetry.title} - ${selectedPoetry.author} (${selectedPoetry.dynasty})

+
+ 目的: ${purpose} + 场景: ${usage} + 读者: ${targetAudience} + 深度: ${depth} + 重点: ${focus} +
+
+ +
+
📖 诗词原文
+
${selectedPoetry.content}
+ +
🔍 ${focus}分析
+

${generateAIAnalysisContent(selectedPoetry, focus, depth)}

+ +
🎯 针对${targetAudience}的解读建议
+

${generateAudienceSpecificAdvice(targetAudience, selectedPoetry)}

+ +
💡 教学/学习建议
+

${generateLearningSuggestions(usage, purpose)}

+ +
📊 文学价值评估
+
+
+ 艺术成就: +
+
+
+
+
+ 历史地位: +
+
+
+
+
+ 文化影响: +
+
+
+
+
+
+ + +
+ `; + + showLoading(false); + + // 滚动到结果区域 + analysisResult.scrollIntoView({ behavior: 'smooth' }); + }, 2000); +} + +// 获取选中的诗词 +function getSelectedPoetry() { + // 这里应该从状态管理获取当前选中的诗词 + // 暂时返回第一首作为示例 + return { + id: 1, + title: "静夜思", + author: "李白", + dynasty: "唐", + content: "床前明月光,疑是地上霜。\n举头望明月,低头思故乡。", + type: "抒情", + wordCount: "五言", + tags: ["思乡", "月亮", "夜晚"] + }; +} + +// 生成AI分析内容 +function generateAIAnalysisContent(poetry, focus, depth) { + const focusTemplates = { + "意境分析": `《${poetry.title}》通过${poetry.content.split(',')[0]}等意象,营造出一种${poetry.tags[0]}的意境。诗人巧妙运用空间对比和时间流逝的描写,使读者感受到${poetry.author}独特的情感表达方式。`, + "修辞手法": `本诗运用了比喻、对仗等修辞手法。如"${poetry.content.split('。')[0]}"一句,通过${poetry.tags[1]}的比喻,增强了诗歌的形象性和感染力。`, + "格律分析": `作为一首${poetry.wordCount}诗,本诗严格遵守古典诗歌的格律要求。平仄搭配得当,押韵工整,体现了${poetry.dynasty}时期诗歌的形式美。`, + "历史背景": `创作于${poetry.dynasty}时期,反映了当时的社会文化背景。${poetry.author}在${poetry.tags[2]}的背景下,通过这首诗表达了...`, + "文学价值": `《${poetry.title}》在中国文学史上具有重要地位,对后世诗歌创作产生了深远影响。其${depth}的文学价值体现在...`, + "综合解析": `从多个角度分析,《${poetry.title}》展现了${poetry.author}高超的艺术造诣。在意境营造、修辞运用、格律把握等方面都达到了很高水平。` + }; + + return focusTemplates[focus] || "AI解析内容生成中..."; +} + +// 生成读者特定建议 +function generateAudienceSpecificAdvice(audience, poetry) { + const adviceTemplates = { + "中小学生": `对于中小学生,建议重点理解诗词的字面意思和基本情感。可以通过绘画、朗诵等方式增强对"${poetry.tags[0]}"主题的理解。`, + "大学生": `大学生可以深入分析诗词的文学技巧和历史背景,探讨${poetry.author}的创作风格及其在文学史上的地位。`, + "文学爱好者": `建议对比阅读${poetry.author}的其他作品,研究其艺术特色的发展变化,深入探讨${poetry.dynasty}诗歌的特点。`, + "研究人员": `可以从学术角度进行深入研究,关注版本校勘、注释考证、文学批评等多个维度,挖掘诗词的深层文化内涵。`, + "普通读者": `建议从情感共鸣入手,欣赏诗词的意境美和语言美,不必过于追求学术性的分析。` + }; + + return adviceTemplates[audience] || "根据读者特点提供个性化解读建议。"; +} + +// 生成学习建议 +function generateLearningSuggestions(usage, purpose) { + const suggestionTemplates = { + "课堂教学": `1. 课前预习:了解诗人生平和创作背景\n2. 课堂讲解:重点分析诗词意象和情感\n3. 课后拓展:相关诗词对比阅读\n4. 实践活动:诗词朗诵或创作练习`, + "自学研究": `1. 建立知识框架:了解${purpose}的基本方法\n2. 深度阅读:查阅相关文献和注释\n3. 笔记整理:记录关键见解和疑问\n4. 实践应用:尝试撰写小论文或赏析文章`, + "文学创作": `1. 模仿练习:学习诗词的意象运用\n2. 技巧分析:研究修辞手法和格律\n3. 创作实践:尝试创作类似主题的诗歌\n4. 修改完善:反复推敲字句和意境`, + "文化传播": `1. 通俗化解读:用现代语言解释古典诗词\n2. 多媒体呈现:结合图片、音频等媒介\n3. 互动设计:设计问答、游戏等互动环节\n4. 社交媒体:制作易于传播的诗词卡片`, + "考试备考": `1. 考点梳理:明确常考知识点\n2. 真题练习:熟悉题型和答题技巧\n3. 记忆方法:使用联想记忆等技巧\n4. 模拟测试:进行限时练习和评估` + }; + + return suggestionTemplates[usage] || "根据使用场景提供具体的学习建议。"; +} + +// 切换收藏状态 +function toggleFavorite(poetryId) { + const favoriteBtn = document.getElementById('favoriteBtn'); + const isFavorite = favoriteBtn.classList.contains('favorited'); + + if (isFavorite) { + favoriteBtn.innerHTML = ' 收藏'; + favoriteBtn.classList.remove('favorited'); + alert('已取消收藏'); + } else { + favoriteBtn.innerHTML = ' 已收藏'; + favoriteBtn.classList.add('favorited'); + alert('已添加到收藏夹'); + } + + console.log(`诗词ID ${poetryId} 收藏状态: ${!isFavorite ? '已收藏' : '已取消'}`); +} + +// 开始AI分析 +function startAIAnalysis(poetry) { + // 设置当前诗词 + console.log('开始AI分析:', poetry.title); + + // 滚动到AI分析区域 + document.getElementById('ai-analysis').scrollIntoView({ behavior: 'smooth' }); + + // 显示提示 + alert(`已选择《${poetry.title}》,请在AI解析区域设置参数并点击"生成AI解析"按钮。`); +} + +// 分享诗词 +function sharePoetry(poetry) { + const shareText = `分享一首古诗词:《${poetry.title}》 - ${poetry.author} (${poetry.dynasty})\n\n${poetry.content}\n\n来自古诗词智能解析器`; + + if (navigator.share) { + navigator.share({ + title: poetry.title, + text: shareText, + url: window.location.href + }); + } else { + // 复制到剪贴板 + navigator.clipboard.writeText(shareText).then(() => { + alert('诗词内容已复制到剪贴板,可以粘贴到其他应用分享!'); + }); + } +} + +// 开始对比分析 +function startComparison() { + alert('对比分析功能:请选择两首诗词进行对比。\n\n演示版本中,此功能需要连接到实际的AI对比分析服务。'); +} + +// 获取推荐 +function getRecommendations() { + alert('相似推荐功能:基于当前诗词推荐主题、风格相似的作品。\n\n演示版本中,此功能需要连接到实际的推荐算法服务。'); +} + +// 开始问答 +function startQA() { + alert('知识问答功能:AI问答关于诗词的各类问题。\n\n演示版本中,此功能需要连接到实际的AI问答服务。'); +} + +// 开始背诵 +function startMemorization() { + alert('背诵助手功能:提供填空测试、顺序排序等背诵辅助。\n\n演示版本中,此功能需要连接到实际的背诵算法服务。'); +} diff --git a/static/js/service-worker.js b/static/js/service-worker.js new file mode 100644 index 0000000..97f59fb --- /dev/null +++ b/static/js/service-worker.js @@ -0,0 +1,217 @@ +// 古诗词智能解析器 - Service Worker +// 支持PWA功能,提供离线访问能力 + +const CACHE_NAME = 'poetry-ai-v1.0.0'; +const urlsToCache = [ + '/', + '/index.html', + '/static/css/style.css', + '/static/js/main.js', + 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css', + 'https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;700&family=Ma+Shan+Zheng&display=swap' +]; + +// 安装Service Worker +self.addEventListener('install', event => { + console.log('Service Worker: 安装中...'); + + event.waitUntil( + caches.open(CACHE_NAME) + .then(cache => { + console.log('Service Worker: 缓存文件中...'); + return cache.addAll(urlsToCache); + }) + .then(() => { + console.log('Service Worker: 安装完成'); + return self.skipWaiting(); + }) + ); +}); + +// 激活Service Worker +self.addEventListener('activate', event => { + console.log('Service Worker: 激活中...'); + + // 清理旧缓存 + event.waitUntil( + caches.keys().then(cacheNames => { + return Promise.all( + cacheNames.map(cacheName => { + if (cacheName !== CACHE_NAME) { + console.log('Service Worker: 清理旧缓存:', cacheName); + return caches.delete(cacheName); + } + }) + ); + }).then(() => { + console.log('Service Worker: 激活完成'); + return self.clients.claim(); + }) + ); +}); + +// 拦截网络请求 +self.addEventListener('fetch', event => { + // 只处理GET请求 + if (event.request.method !== 'GET') return; + + // 对于API请求,使用网络优先策略 + if (event.request.url.includes('/api/')) { + event.respondWith( + fetch(event.request) + .then(response => { + // 克隆响应以进行缓存 + const responseToCache = response.clone(); + + caches.open(CACHE_NAME) + .then(cache => { + cache.put(event.request, responseToCache); + }); + + return response; + }) + .catch(() => { + // 网络失败时尝试从缓存获取 + return caches.match(event.request); + }) + ); + return; + } + + // 对于静态资源,使用缓存优先策略 + event.respondWith( + caches.match(event.request) + .then(cachedResponse => { + if (cachedResponse) { + console.log('Service Worker: 从缓存返回:', event.request.url); + return cachedResponse; + } + + // 缓存中没有,从网络获取 + return fetch(event.request) + .then(response => { + // 检查响应是否有效 + if (!response || response.status !== 200 || response.type !== 'basic') { + return response; + } + + // 克隆响应以进行缓存 + const responseToCache = response.clone(); + + caches.open(CACHE_NAME) + .then(cache => { + cache.put(event.request, responseToCache); + }); + + return response; + }) + .catch(error => { + console.log('Service Worker: 获取失败:', error); + + // 对于HTML页面,返回离线页面 + if (event.request.headers.get('accept').includes('text/html')) { + return caches.match('/index.html'); + } + + // 对于其他资源,可以返回一个占位符 + return new Response('网络连接失败,请检查网络设置。', { + status: 408, + headers: { 'Content-Type': 'text/plain' } + }); + }); + }) + ); +}); + +// 处理推送通知 +self.addEventListener('push', event => { + console.log('Service Worker: 收到推送通知'); + + const options = { + body: event.data ? event.data.text() : '古诗词智能解析器有新内容更新', + icon: '/static/images/icon-192.png', + badge: '/static/images/badge-72.png', + vibrate: [100, 50, 100], + data: { + dateOfArrival: Date.now(), + primaryKey: '1' + }, + actions: [ + { + action: 'explore', + title: '探索诗词', + icon: '/static/images/explore-icon.png' + }, + { + action: 'close', + title: '关闭', + icon: '/static/images/close-icon.png' + } + ] + }; + + event.waitUntil( + self.registration.showNotification('古诗词智能解析器', options) + ); +}); + +// 处理通知点击 +self.addEventListener('notificationclick', event => { + console.log('Service Worker: 通知被点击'); + + event.notification.close(); + + if (event.action === 'explore') { + // 用户点击了"探索诗词"按钮 + event.waitUntil( + clients.openWindow('/') + ); + } else { + // 用户点击了通知主体 + event.waitUntil( + clients.matchAll({ + type: 'window', + includeUncontrolled: true + }).then(clientList => { + // 如果已经有打开的窗口,聚焦它 + for (const client of clientList) { + if (client.url === '/' && 'focus' in client) { + return client.focus(); + } + } + + // 否则打开新窗口 + if (clients.openWindow) { + return clients.openWindow('/'); + } + }) + ); + } +}); + +// 处理后台同步 +self.addEventListener('sync', event => { + console.log('Service Worker: 后台同步:', event.tag); + + if (event.tag === 'sync-favorites') { + event.waitUntil(syncFavorites()); + } +}); + +// 同步收藏数据 +function syncFavorites() { + console.log('Service Worker: 同步收藏数据'); + + // 这里应该实现实际的同步逻辑 + // 暂时只是记录日志 + return Promise.resolve(); +} + +// 处理消息 +self.addEventListener('message', event => { + console.log('Service Worker: 收到消息:', event.data); + + if (event.data && event.data.type === 'SKIP_WAITING') { + self.skipWaiting(); + } +});