初始化提交

This commit is contained in:
2025-12-21 00:33:04 +08:00
parent d6e0f0b591
commit 4f6ed3d3e6
9 changed files with 2468 additions and 0 deletions

210
api/app.py Normal file
View File

@@ -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/<int:poetry_id>', 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)

322
index.html Normal file
View File

@@ -0,0 +1,322 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>古诗词智能查询与解析器</title>
<link rel="stylesheet" href="static/css/style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;700&family=Ma+Shan+Zheng&display=swap" rel="stylesheet">
<link rel="manifest" href="manifest.json">
<link rel="icon" href="static/images/favicon.ico" type="image/x-icon">
</head>
<body>
<!-- 导航栏 -->
<nav class="navbar">
<div class="container">
<div class="logo">
<i class="fas fa-book-open"></i>
<h1>古诗词智能解析器</h1>
</div>
<div class="nav-links">
<a href="#home" class="active"><i class="fas fa-home"></i> 首页</a>
<a href="#search"><i class="fas fa-search"></i> 查询</a>
<a href="#browse"><i class="fas fa-list"></i> 浏览</a>
<a href="#ai-analysis"><i class="fas fa-robot"></i> AI解析</a>
<a href="#learning"><i class="fas fa-graduation-cap"></i> 学习</a>
<a href="#personal"><i class="fas fa-user"></i> 个人中心</a>
</div>
<button class="menu-toggle" id="menuToggle">
<i class="fas fa-bars"></i>
</button>
</div>
</nav>
<!-- 主内容区 -->
<main class="container">
<!-- 首页横幅 -->
<section id="home" class="hero">
<div class="hero-content">
<h2>探索千年诗词之美</h2>
<p>AI智能解析深度理解古诗词的意境与内涵</p>
<div class="search-box">
<input type="text" id="quickSearch" placeholder="输入诗词标题、作者、诗句或关键词...">
<button id="quickSearchBtn"><i class="fas fa-search"></i> 智能搜索</button>
</div>
<div class="quick-filters">
<span>快速筛选:</span>
<button class="filter-btn" data-dynasty="唐">唐代</button>
<button class="filter-btn" data-dynasty="宋">宋代</button>
<button class="filter-btn" data-type="山水">山水诗</button>
<button class="filter-btn" data-type="抒情">抒情诗</button>
</div>
</div>
</section>
<!-- 智能查询模块 -->
<section id="search" class="section">
<h2><i class="fas fa-search"></i> 智能查询</h2>
<div class="search-panel">
<div class="search-form">
<div class="form-group">
<label for="poetryTitle"><i class="fas fa-heading"></i> 诗词标题</label>
<input type="text" id="poetryTitle" placeholder="如:静夜思、春晓...">
</div>
<div class="form-group">
<label for="author"><i class="fas fa-user"></i> 作者</label>
<input type="text" id="author" placeholder="如:李白、杜甫...">
</div>
<div class="form-group">
<label for="dynasty"><i class="fas fa-landmark"></i> 朝代</label>
<select id="dynasty">
<option value="">全部朝代</option>
<option value="唐">唐代</option>
<option value="宋">宋代</option>
<option value="元">元代</option>
<option value="明">明代</option>
<option value="清">清代</option>
<option value="先秦">先秦</option>
<option value="汉">汉代</option>
<option value="魏晋">魏晋南北朝</option>
</select>
</div>
<div class="form-group">
<label for="keywords"><i class="fas fa-key"></i> 关键词/诗句</label>
<input type="text" id="keywords" placeholder="输入诗句片段或关键词...">
</div>
<div class="form-group">
<label for="poetryType"><i class="fas fa-tags"></i> 题材</label>
<select id="poetryType">
<option value="">全部题材</option>
<option value="山水">山水田园</option>
<option value="边塞">边塞战争</option>
<option value="咏物">咏物言志</option>
<option value="抒情">抒情诗</option>
<option value="叙事">叙事诗</option>
<option value="哲理">哲理诗</option>
<option value="送别">送别诗</option>
</select>
</div>
<div class="form-group">
<label for="wordCount"><i class="fas fa-text-height"></i> 字数</label>
<select id="wordCount">
<option value="">不限</option>
<option value="五言">五言</option>
<option value="七言">七言</option>
<option value="杂言">杂言</option>
<option value="词"></option>
</select>
</div>
<button id="advancedSearchBtn" class="btn-primary">
<i class="fas fa-search-plus"></i> 高级搜索
</button>
<button id="resetSearchBtn" class="btn-secondary">
<i class="fas fa-redo"></i> 重置
</button>
</div>
</div>
</section>
<!-- AI解析模块 -->
<section id="ai-analysis" class="section">
<h2><i class="fas fa-robot"></i> AI深度解析</h2>
<div class="ai-analysis-panel">
<div class="analysis-controls">
<div class="form-group">
<label for="purpose"><i class="fas fa-bullseye"></i> 查询目的</label>
<select id="purpose">
<option value="学习理解">学习理解</option>
<option value="教学参考">教学参考</option>
<option value="文学研究">文学研究</option>
<option value="创作参考">创作参考</option>
<option value="文化欣赏">文化欣赏</option>
</select>
</div>
<div class="form-group">
<label for="usage"><i class="fas fa-scenario"></i> 使用场景</label>
<select id="usage">
<option value="课堂教学">课堂教学</option>
<option value="自学研究">自学研究</option>
<option value="文学创作">文学创作</option>
<option value="文化传播">文化传播</option>
<option value="考试备考">考试备考</option>
</select>
</div>
<div class="form-group">
<label for="targetAudience"><i class="fas fa-users"></i> 目标读者</label>
<select id="targetAudience">
<option value="中小学生">中小学生</option>
<option value="大学生">大学生</option>
<option value="文学爱好者">文学爱好者</option>
<option value="研究人员">研究人员</option>
<option value="普通读者">普通读者</option>
</select>
</div>
<div class="form-group">
<label for="depth"><i class="fas fa-layer-group"></i> 解析深度</label>
<select id="depth">
<option value="基础">基础解析</option>
<option value="中等">中等深度</option>
<option value="深入">深入解析</option>
<option value="专业">专业级分析</option>
</select>
</div>
<div class="form-group">
<label for="focus"><i class="fas fa-crosshairs"></i> 关注重点</label>
<select id="focus">
<option value="意境分析">意境分析</option>
<option value="修辞手法">修辞手法</option>
<option value="格律分析">格律分析</option>
<option value="历史背景">历史背景</option>
<option value="文学价值">文学价值</option>
<option value="综合解析">综合解析</option>
</select>
</div>
<button id="generateAnalysisBtn" class="btn-primary">
<i class="fas fa-magic"></i> 生成AI解析
</button>
</div>
<div class="analysis-result" id="analysisResult">
<div class="result-placeholder">
<i class="fas fa-book-reader"></i>
<h3>AI解析结果将显示在这里</h3>
<p>选择诗词并设置解析参数后,点击"生成AI解析"按钮</p>
</div>
</div>
</div>
</section>
<!-- 诗词展示区 -->
<section id="browse" class="section">
<h2><i class="fas fa-list"></i> 诗词浏览</h2>
<div class="browse-controls">
<div class="view-toggle">
<button class="view-btn active" data-view="grid"><i class="fas fa-th"></i> 网格</button>
<button class="view-btn" data-view="list"><i class="fas fa-list"></i> 列表</button>
</div>
<div class="sort-controls">
<select id="sortBy">
<option value="time">按年代排序</option>
<option value="popularity">按热度排序</option>
<option value="title">按标题排序</option>
</select>
</div>
</div>
<div class="poetry-grid" id="poetryGrid">
<!-- 诗词卡片将通过JavaScript动态加载 -->
</div>
<div class="loading" id="loadingIndicator">
<i class="fas fa-spinner fa-spin"></i> 加载中...
</div>
</section>
<!-- 交互学习功能 -->
<section id="learning" class="section">
<h2><i class="fas fa-graduation-cap"></i> 交互学习</h2>
<div class="learning-features">
<div class="feature-card">
<div class="feature-icon">
<i class="fas fa-balance-scale"></i>
</div>
<h3>对比分析</h3>
<p>比较两首诗词的异同,深入理解不同风格</p>
<button class="btn-secondary" id="compareBtn">开始对比</button>
</div>
<div class="feature-card">
<div class="feature-icon">
<i class="fas fa-lightbulb"></i>
</div>
<h3>相似推荐</h3>
<p>基于当前诗词推荐主题、风格相似的作品</p>
<button class="btn-secondary" id="recommendBtn">获取推荐</button>
</div>
<div class="feature-card">
<div class="feature-icon">
<i class="fas fa-question-circle"></i>
</div>
<h3>知识问答</h3>
<p>AI问答功能解答关于诗词的各类问题</p>
<button class="btn-secondary" id="qaBtn">开始问答</button>
</div>
<div class="feature-card">
<div class="feature-icon">
<i class="fas fa-brain"></i>
</div>
<h3>背诵助手</h3>
<p>填空测试、顺序排序等背诵辅助功能</p>
<button class="btn-secondary" id="memorizeBtn">开始背诵</button>
</div>
</div>
</section>
</main>
<!-- 页脚 -->
<footer>
<div class="container">
<div class="footer-content">
<div class="footer-section">
<h3><i class="fas fa-book-open"></i> 古诗词智能解析器</h3>
<p>探索中华诗词之美,传承千年文化精髓</p>
</div>
<div class="footer-section">
<h4>功能模块</h4>
<a href="#search">智能查询</a>
<a href="#ai-analysis">AI解析</a>
<a href="#browse">诗词浏览</a>
<a href="#learning">交互学习</a>
</div>
<div class="footer-section">
<h4>技术支持</h4>
<a href="#" id="apiDocs">API文档</a>
<a href="#" id="aboutAi">AI技术说明</a>
<a href="#" id="privacy">隐私政策</a>
<a href="#" id="contact">联系我们</a>
</div>
<div class="footer-section">
<h4>关注我们</h4>
<div class="social-links">
<a href="#"><i class="fab fa-weixin"></i></a>
<a href="#"><i class="fab fa-weibo"></i></a>
<a href="#"><i class="fab fa-github"></i></a>
<a href="#"><i class="fab fa-bilibili"></i></a>
</div>
</div>
</div>
<div class="footer-bottom">
<p>&copy; 2023 古诗词智能解析器 | 基于H5技术开发 | PWA支持</p>
<div class="pwa-badge">
<i class="fas fa-download"></i> 可添加到主屏幕
</div>
</div>
</div>
</footer>
<!-- 模态框 -->
<div class="modal" id="poetryDetailModal">
<div class="modal-content">
<div class="modal-header">
<h3 id="modalTitle">诗词详情</h3>
<button class="close-modal">&times;</button>
</div>
<div class="modal-body" id="modalBody">
<!-- 诗词详情内容将通过JavaScript动态加载 -->
</div>
<div class="modal-footer">
<button class="btn-secondary" id="favoriteBtn">
<i class="far fa-heart"></i> 收藏
</button>
<button class="btn-primary" id="analyzeBtn">
<i class="fas fa-robot"></i> AI解析
</button>
<button class="btn-secondary" id="shareBtn">
<i class="fas fa-share-alt"></i> 分享
</button>
</div>
</div>
</div>
<!-- 脚本 -->
<script src="static/js/main.js"></script>
<script src="static/js/service-worker.js"></script>
</body>
</html>

127
manifest.json Normal file
View File

@@ -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智能解析",
"离线阅读",
"诗词收藏",
"学习记录"
]
}

4
requirements.txt Normal file
View File

@@ -0,0 +1,4 @@
Flask==2.3.3
Flask-CORS==4.0.0
requests==2.31.0
python-dotenv==1.0.0

107
run.py Normal file
View File

@@ -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()

28
start_app.bat Normal file
View File

@@ -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

708
static/css/style.css Normal file
View File

@@ -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);
}

745
static/js/main.js Normal file
View File

@@ -0,0 +1,745 @@
// 古诗词智能查询与解析器 - 主JavaScript文件
document.addEventListener('DOMContentLoaded', function() {
// 初始化应用
initApp();
// 加载示例诗词数据
loadSamplePoetryData();
// 设置事件监听器
setupEventListeners();
});
// 应用初始化
function initApp() {
console.log('古诗词智能解析器应用已启动');
// 设置当前年份
document.querySelector('.footer-bottom p').innerHTML =
`&copy; ${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 WorkerPWA功能可用');
// 注册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 = `
<div class="poetry-card-header">
<h3>${poetry.title}</h3>
<div class="meta">
<span>${poetry.author}</span>
<span>${poetry.dynasty}</span>
</div>
</div>
<div class="poetry-card-body">
<div class="poetry-content">${poetry.content.replace(/\n/g, '<br>')}</div>
<div class="poetry-tags">
${poetry.tags.map(tag => `<span class="tag">${tag}</span>`).join('')}
</div>
</div>
`;
// 添加点击事件
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 = `
<div class="poetry-detail">
<div class="detail-header">
<h4>${poetry.title}</h4>
<div class="detail-meta">
<span><i class="fas fa-user"></i> ${poetry.author}</span>
<span><i class="fas fa-landmark"></i> ${poetry.dynasty}</span>
<span><i class="fas fa-tag"></i> ${poetry.type}</span>
<span><i class="fas fa-text-height"></i> ${poetry.wordCount}</span>
</div>
</div>
<div class="detail-content">
<h5>原文:</h5>
<pre>${poetry.content}</pre>
<h5>现代汉语翻译:</h5>
<p>${getTranslation(poetry)}</p>
<h5>简要赏析:</h5>
<p>${getBriefAnalysis(poetry)}</p>
</div>
<div class="detail-tags">
<h5>标签:</h5>
<div class="tags">
${poetry.tags.map(tag => `<span class="tag">${tag}</span>`).join('')}
</div>
</div>
</div>
`;
// 更新按钮事件
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 = `
<div class="search-result">
<h3><i class="fas fa-search"></i> 搜索结果:${query}</h3>
<p>找到 <strong>6</strong> 首相关诗词</p>
<div class="result-list">
<p>1. 静夜思 - 李白 (唐代)</p>
<p>2. 春晓 - 孟浩然 (唐代)</p>
<p>3. 水调歌头·明月几时有 - 苏轼 (宋代)</p>
<p>4. 登鹳雀楼 - 王之涣 (唐代)</p>
<p>5. 望庐山瀑布 - 李白 (唐代)</p>
<p>6. 江雪 - 柳宗元 (唐代)</p>
</div>
<p class="note">注这是演示数据实际应用中会连接到真实的诗词数据库和AI解析服务。</p>
</div>
`;
// 滚动到结果区域
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 = `
<div class="ai-analysis-result">
<h3><i class="fas fa-robot"></i> AI深度解析结果</h3>
<div class="analysis-header">
<h4>${selectedPoetry.title} - ${selectedPoetry.author} (${selectedPoetry.dynasty})</h4>
<div class="analysis-meta">
<span><i class="fas fa-bullseye"></i> 目的: ${purpose}</span>
<span><i class="fas fa-scenario"></i> 场景: ${usage}</span>
<span><i class="fas fa-users"></i> 读者: ${targetAudience}</span>
<span><i class="fas fa-layer-group"></i> 深度: ${depth}</span>
<span><i class="fas fa-crosshairs"></i> 重点: ${focus}</span>
</div>
</div>
<div class="analysis-content">
<h5>📖 诗词原文</h5>
<pre>${selectedPoetry.content}</pre>
<h5>🔍 ${focus}分析</h5>
<p>${generateAIAnalysisContent(selectedPoetry, focus, depth)}</p>
<h5>🎯 针对${targetAudience}的解读建议</h5>
<p>${generateAudienceSpecificAdvice(targetAudience, selectedPoetry)}</p>
<h5>💡 教学/学习建议</h5>
<p>${generateLearningSuggestions(usage, purpose)}</p>
<h5>📊 文学价值评估</h5>
<div class="value-assessment">
<div class="assessment-item">
<span>艺术成就:</span>
<div class="progress-bar">
<div class="progress" style="width: ${85 + Math.random() * 10}%"></div>
</div>
</div>
<div class="assessment-item">
<span>历史地位:</span>
<div class="progress-bar">
<div class="progress" style="width: ${80 + Math.random() * 15}%"></div>
</div>
</div>
<div class="assessment-item">
<span>文化影响:</span>
<div class="progress-bar">
<div class="progress" style="width: ${75 + Math.random() * 20}%"></div>
</div>
</div>
</div>
</div>
<div class="analysis-footer">
<p class="note"><i class="fas fa-info-circle"></i> 此解析由AI生成基于深度学习和古典文学知识库。实际应用中会连接到真实的AI解析服务。</p>
</div>
</div>
`;
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 = '<i class="far fa-heart"></i> 收藏';
favoriteBtn.classList.remove('favorited');
alert('已取消收藏');
} else {
favoriteBtn.innerHTML = '<i class="fas fa-heart"></i> 已收藏';
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演示版本中此功能需要连接到实际的背诵算法服务。');
}

217
static/js/service-worker.js Normal file
View File

@@ -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();
}
});