feat: v2.2.0 智能新闻更新和布局优化
- 实现每日首次访问自动更新新闻功能 - 每个网站获取3条一周内的新闻 - 新闻模块放置在左侧主栏 - 相似推荐移至右侧边栏 - 自动去重防止重复新闻
This commit is contained in:
64
app.py
64
app.py
@@ -116,6 +116,70 @@ def create_app(config_name='default'):
|
|||||||
site.view_count += 1
|
site.view_count += 1
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
# 智能新闻更新:检查今天是否已更新过新闻
|
||||||
|
from datetime import date
|
||||||
|
today = date.today()
|
||||||
|
|
||||||
|
# 检查该网站最新一条新闻的创建时间
|
||||||
|
latest_news = News.query.filter_by(
|
||||||
|
site_id=site.id
|
||||||
|
).order_by(News.created_at.desc()).first()
|
||||||
|
|
||||||
|
# 判断是否需要更新新闻
|
||||||
|
need_update = False
|
||||||
|
if not latest_news:
|
||||||
|
# 没有任何新闻,需要获取
|
||||||
|
need_update = True
|
||||||
|
elif latest_news.created_at.date() < today:
|
||||||
|
# 最新新闻不是今天创建的,需要更新
|
||||||
|
need_update = True
|
||||||
|
|
||||||
|
# 如果需要更新,自动获取最新新闻
|
||||||
|
if need_update:
|
||||||
|
api_key = app.config.get('BOCHA_API_KEY')
|
||||||
|
if api_key:
|
||||||
|
try:
|
||||||
|
# 创建新闻搜索器
|
||||||
|
searcher = NewsSearcher(api_key)
|
||||||
|
|
||||||
|
# 获取新闻(限制3条,一周内的)
|
||||||
|
news_items = searcher.search_site_news(
|
||||||
|
site_name=site.name,
|
||||||
|
site_url=site.url,
|
||||||
|
count=3,
|
||||||
|
freshness='oneWeek'
|
||||||
|
)
|
||||||
|
|
||||||
|
# 保存新闻到数据库
|
||||||
|
if news_items:
|
||||||
|
for item in news_items:
|
||||||
|
# 检查是否已存在(根据URL去重)
|
||||||
|
existing = News.query.filter_by(
|
||||||
|
site_id=site.id,
|
||||||
|
url=item['url']
|
||||||
|
).first()
|
||||||
|
|
||||||
|
if not existing:
|
||||||
|
news = News(
|
||||||
|
site_id=site.id,
|
||||||
|
title=item['title'],
|
||||||
|
content=item.get('summary') or item.get('snippet', ''),
|
||||||
|
url=item['url'],
|
||||||
|
source_name=item.get('site_name', ''),
|
||||||
|
source_icon=item.get('site_icon', ''),
|
||||||
|
published_at=item.get('published_at'),
|
||||||
|
news_type='Search Result',
|
||||||
|
is_active=True
|
||||||
|
)
|
||||||
|
db.session.add(news)
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
# 获取新闻失败,不影响页面显示
|
||||||
|
print(f"自动获取新闻失败:{str(e)}")
|
||||||
|
db.session.rollback()
|
||||||
|
|
||||||
# 获取该网站的相关新闻(最多显示5条)
|
# 获取该网站的相关新闻(最多显示5条)
|
||||||
news_list = News.query.filter_by(
|
news_list = News.query.filter_by(
|
||||||
site_id=site.id,
|
site_id=site.id,
|
||||||
|
|||||||
@@ -669,7 +669,10 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 侧边栏 -->
|
||||||
|
<div class="sidebar-column">
|
||||||
<!-- Similar Recommendations -->
|
<!-- Similar Recommendations -->
|
||||||
{% if recommended_sites %}
|
{% if recommended_sites %}
|
||||||
<div class="content-block">
|
<div class="content-block">
|
||||||
@@ -677,35 +680,22 @@
|
|||||||
<span>✨</span>
|
<span>✨</span>
|
||||||
相似推荐
|
相似推荐
|
||||||
</h2>
|
</h2>
|
||||||
<div class="recommendations-grid">
|
|
||||||
{% for rec_site in recommended_sites %}
|
{% for rec_site in recommended_sites %}
|
||||||
<a href="/site/{{ rec_site.code }}" class="recommendation-card">
|
<a href="/site/{{ rec_site.code }}" class="recommendation-card" style="display: flex; gap: 12px; padding: 16px; border: 1px solid var(--border-color); border-radius: 12px; margin-bottom: 12px; text-decoration: none; transition: all 0.2s;">
|
||||||
{% if rec_site.logo %}
|
{% if rec_site.logo %}
|
||||||
<img src="{{ rec_site.logo }}" alt="{{ rec_site.name }}" class="rec-logo">
|
<img src="{{ rec_site.logo }}" alt="{{ rec_site.name }}" style="width: 48px; height: 48px; border-radius: 8px; flex-shrink: 0;">
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="rec-logo" style="background: linear-gradient(135deg, #0ea5e9 0%, #8b5cf6 100%);"></div>
|
<div style="width: 48px; height: 48px; border-radius: 8px; background: linear-gradient(135deg, #0ea5e9 0%, #8b5cf6 100%); flex-shrink: 0;"></div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="rec-info">
|
<div style="flex: 1; min-width: 0;">
|
||||||
<h4>{{ rec_site.name }}</h4>
|
<h4 style="font-size: 14px; font-weight: 600; margin: 0 0 4px 0; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{{ rec_site.name }}</h4>
|
||||||
<p>{{ rec_site.short_desc or rec_site.description }}</p>
|
<p style="font-size: 12px; color: var(--text-secondary); margin: 0; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;">{{ rec_site.short_desc or rec_site.description }}</p>
|
||||||
<div class="rec-tags">
|
|
||||||
{% for tag in rec_site.tags[:2] %}
|
|
||||||
<span class="rec-tag">{{ tag.name }}</span>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<span class="arrow-icon">↗</span>
|
|
||||||
</a>
|
</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 侧边栏 -->
|
|
||||||
<div class="sidebar-column">
|
|
||||||
<!-- 预留侧边栏位置,可以后续添加其他模块 -->
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
Reference in New Issue
Block a user