初始化红餐观察库项目

This commit is contained in:
freedakgmail
2026-07-19 18:11:08 +08:00
commit c663539548
22 changed files with 1261 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
{% extends "base.html" %}
{% block title %}{{ article.title }} · 红餐观察库{% endblock %}
{% block content %}
<div class="reading-layout">
<article class="story">
<a class="back" href="/">← 返回文章库</a>
<header>
<div class="story-meta"><time>{{ article.published_at|date_cn }}</time><span>{{ article.author or '红餐网' }}</span></div>
<h1>{{ article.title }}</h1>
{% if article.summary %}<p class="dek">{{ article.summary }}</p>{% endif %}
<a class="source-link" href="{{ article.canonical_url }}" target="_blank" rel="noopener">查看原文 ↗</a>
</header>
<div class="story-body">
{% for paragraph in article.content.split('\n') if paragraph.strip() %}<p>{{ paragraph }}</p>{% endfor %}
</div>
</article>
<aside class="analysis-panel">
<div class="analysis-head"><div><span>QWEN ANALYSIS</span><h2>编辑部研判</h2></div><button id="analyzeBtn" data-id="{{ article.id }}">{% if analysis %}重新分析{% else %}开始分析{% endif %}</button></div>
<div id="analysisStatus" class="analysis-status" hidden></div>
<div id="analysisContent">
{% if analysis %}
<section><h3>一句话摘要</h3><p>{{ analysis.summary }}</p></section>
<section><h3>核心要点</h3><ul>{% for x in analysis.key_points %}<li>{{ x }}</li>{% endfor %}</ul></section>
<section><h3>行业信号</h3><p>{{ analysis.industry_signal }}</p></section>
<section><h3>延展选题</h3><ol>{% for x in analysis.content_angles %}<li>{{ x }}</li>{% endfor %}</ol></section>
<section><h3>标签</h3><div class="tags">{% for x in analysis.tags %}<span>{{ x }}</span>{% endfor %}</div></section>
{% else %}
<div class="analysis-empty"><div class="scan-lines"></div><h3>等待 AI 阅读</h3><p>千问将提炼文章摘要、行业信号、关键数据和可延展选题。</p></div>
{% endif %}
</div>
</aside>
</div>
{% endblock %}
{% block scripts %}<script src="{{ url_for('static', filename='app.js') }}"></script>{% endblock %}
+24
View File
@@ -0,0 +1,24 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="color-scheme" content="light">
<title>{% block title %}红餐观察库{% endblock %}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='app.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='ai-summary.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='signals.css') }}">
</head>
<body>
<header class="site-header">
<a class="brand" href="/" aria-label="返回文章库首页">
<span class="brand-mark">HC</span>
<span><b>红餐观察库</b><small>ARTICLE INTELLIGENCE</small></span>
</a>
<nav><a href="/">文章库</a><span class="system-dot"></span><span>本地运行</span></nav>
</header>
<main>{% block content %}{% endblock %}</main>
<footer><span>红餐文章本地研究工具</span><span>SQLite · Playwright · Qwen</span></footer>
{% block scripts %}{% endblock %}
</body>
</html>
+61
View File
@@ -0,0 +1,61 @@
{% extends "base.html" %}
{% block content %}
<section class="masthead">
<div>
<p class="kicker">餐饮行业内容情报</p>
<h1>从文章堆里,<br>读出行业信号。</h1>
</div>
<form class="search" method="get" role="search">
<label for="q">搜索标题、品牌或正文</label>
<div><input id="q" name="q" value="{{ query }}" placeholder="例如:咖啡、海底捞、供应链"><button>搜索</button></div>
<p>已收录 {{ stats.total }} 篇,{{ stats.analyzed or 0 }} 篇完成 AI 分析</p>
</form>
</section>
<section class="metrics" aria-label="文章库数据">
<div><strong>{{ stats.success }}</strong><span>完整文章</span></div>
<div><strong>{{ stats.analyzed or 0 }}</strong><span>AI 分析</span></div>
<div><strong>{{ stats.latest|date_cn }}</strong><span>最近更新</span></div>
</section>
{% if signals and not query and page == 1 %}
<section class="signals-block">
<div class="signals-title"><div><h2>今日行业信号</h2><p>基于多篇文章交叉提炼,不是单篇新闻复述</p></div><time>{{ signals[0].signal_date }}</time></div>
<div class="signal-grid">
{% for signal in signals %}
<a class="signal-card" href="/signals/{{ signal.id }}">
<div><span class="trend trend-{{ signal.trend }}">{{ signal.trend }}</span><strong>{{ (signal.confidence * 100)|round|int }}%</strong></div>
<h3>{{ signal.title }}</h3><p>{{ signal.summary }}</p>
<div class="signal-tags">{% for tag in signal.tags[:3] %}<span>{{ tag }}</span>{% endfor %}</div>
</a>
{% endfor %}
</div>
</section>
{% endif %}
<section class="library-head">
<div><h2>{% if query %}“{{ query }}”的结果{% else %}最新入库{% endif %}</h2><p>共 {{ total }} 篇</p></div>
{% if query %}<a href="/">清除搜索</a>{% endif %}
</section>
<section class="article-grid">
{% for item in articles %}
<article class="article-card">
<div class="card-meta"><time>{{ item.published_at|date_cn }}</time>{% if item.analyzed %}<span>AI 已分析</span>{% endif %}</div>
<h3><a href="/article/{{ item.id }}">{{ item.title }}</a></h3>
{% if item.ai_summary %}<p class="ai-summary"><b>AI 摘要</b>{{ item.ai_summary }}</p>{% else %}<p>{{ item.summary or item.excerpt }}</p>{% endif %}
<a class="read-link" href="/article/{{ item.id }}">阅读全文 <span></span></a>
</article>
{% else %}
<div class="empty"><h3>没有找到相关文章</h3><p>换一个品牌名、品类或行业关键词试试。</p></div>
{% endfor %}
</section>
{% if pages > 1 %}
<nav class="pagination" aria-label="分页">
{% if page > 1 %}<a href="?q={{ query|urlencode }}&page={{ page-1 }}">上一页</a>{% endif %}
<span>{{ page }} / {{ pages }}</span>
{% if page < pages %}<a href="?q={{ query|urlencode }}&page={{ page+1 }}">下一页</a>{% endif %}
</nav>
{% endif %}
{% endblock %}
+11
View File
@@ -0,0 +1,11 @@
{% extends "base.html" %}
{% block title %}{{ signal.title }} · 行业信号{% endblock %}
{% block content %}
<article class="signal-page">
<a class="back" href="/">← 返回行业信号</a>
<header><span class="trend trend-{{ signal.trend }}">{{ signal.trend }}</span><p>{{ signal.signal_date }} · 置信度 {{ (signal.confidence*100)|round|int }}%</p><h1>{{ signal.title }}</h1><div class="signal-lead">{{ signal.summary }}</div></header>
<section><h2>经营启示</h2><ol>{% for item in implications %}<li>{{ item }}</li>{% endfor %}</ol></section>
<section><h2>证据文章</h2>{% for item in articles %}<a class="evidence" href="/article/{{ item.id }}"><time>{{ item.published_at|date_cn }}</time><span>{{ item.title }}</span></a>{% endfor %}</section>
<div class="tags">{% for tag in tags %}<span>{{ tag }}</span>{% endfor %}</div>
</article>
{% endblock %}