release: v2.2.0 - 博查新闻搜索功能 (生产环境部署版)
核心功能: - 集成博查Web Search API自动获取网站相关新闻 - 智能新闻更新机制(每日首次访问触发) - 精确新闻搜索(使用引号强制匹配网站名称) - News模型扩展(source_name, source_icon字段) - 网站详情页新闻展示模块 - 新闻来源网站信息展示 - 自动去重防止重复新闻 技术实现: - NewsSearcher工具类封装博查API - 数据库迁移脚本migrate_news_fields.py - 测试脚本test_news_feature.py - 定期任务脚本fetch_news_cron.py - API路由:/api/fetch-site-news, /api/fetch-all-news 配置优化: - 修复manage.sh路径和启动命令 - 博查API配置(BOCHA_API_KEY, BOCHA_BASE_URL) - 新闻搜索参数配置 界面优化: - 详情页新闻模块(左侧主栏) - 相似推荐模块(右侧边栏) - 首页标签图标修复 - 后台添加修改密码功能 - 登录页面优化 部署信息: - 部署日期: 2025-12-30 - 部署方式: 手动上传文件 - 数据库: 已迁移(添加source_name和source_icon字段)
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.category-tab {
|
||||
@@ -58,6 +59,74 @@
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.category-tab .tag-count {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 20px;
|
||||
height: 20px;
|
||||
padding: 0 6px;
|
||||
background: rgba(100, 116, 139, 0.1);
|
||||
color: var(--text-secondary);
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
border-radius: 10px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.category-tab.active .tag-count {
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.category-tab:hover .tag-count {
|
||||
background: rgba(59, 130, 246, 0.15);
|
||||
color: var(--primary-blue);
|
||||
}
|
||||
|
||||
.category-tab.active:hover .tag-count {
|
||||
background: rgba(255, 255, 255, 0.35);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.category-tab.hidden-tag {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.category-tab.show-all .hidden-tag {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.more-tags-btn {
|
||||
padding: 10px 20px;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 50px;
|
||||
background: var(--bg-white);
|
||||
color: var(--primary-blue);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.more-tags-btn:hover {
|
||||
border-color: var(--primary-blue);
|
||||
background: rgba(59, 130, 246, 0.05);
|
||||
}
|
||||
|
||||
.more-tags-btn .expand-icon {
|
||||
font-size: 14px;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
.more-tags-btn.expanded .expand-icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.category-tab:hover {
|
||||
border-color: var(--primary-blue);
|
||||
color: var(--primary-blue);
|
||||
@@ -69,8 +138,8 @@
|
||||
color: white;
|
||||
}
|
||||
|
||||
.category-tab .material-symbols-outlined {
|
||||
font-size: 18px;
|
||||
.category-tab .icon {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* 工具网格 */
|
||||
@@ -187,10 +256,6 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tool-views .material-symbols-outlined {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* 分页 */
|
||||
.pagination {
|
||||
display: flex;
|
||||
@@ -243,7 +308,7 @@
|
||||
padding: 80px 20px;
|
||||
}
|
||||
|
||||
.empty-state .material-symbols-outlined {
|
||||
.empty-state .icon {
|
||||
font-size: 64px;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 16px;
|
||||
@@ -286,25 +351,32 @@
|
||||
|
||||
<!-- 分类过滤 -->
|
||||
<div class="categories" id="categories">
|
||||
<div class="category-tabs">
|
||||
<div class="category-tabs" id="categoryTabs">
|
||||
<a href="/" class="category-tab {% if not selected_tag %}active{% endif %}">
|
||||
All Tools
|
||||
</a>
|
||||
{% for tag in tags %}
|
||||
<a href="/?tag={{ tag.slug }}" class="category-tab {% if selected_tag and selected_tag.id == tag.id %}active{% endif %}">
|
||||
<span class="material-symbols-outlined">
|
||||
{% if 'Chat' in tag.name or 'GPT' in tag.name %}chat
|
||||
{% elif 'Image' in tag.name or '图' in tag.name %}image
|
||||
{% elif 'Video' in tag.name or '视频' in tag.name %}videocam
|
||||
{% elif 'Writing' in tag.name or '写作' in tag.name %}edit_note
|
||||
{% elif 'Coding' in tag.name or '代码' in tag.name %}code
|
||||
{% elif 'Audio' in tag.name or '音频' in tag.name %}graphic_eq
|
||||
{% elif '3D' in tag.name %}view_in_ar
|
||||
{% else %}label{% endif %}
|
||||
<a href="/?tag={{ tag.slug }}" class="category-tab {% if selected_tag and selected_tag.id == tag.id %}active{% endif %} {% if loop.index > 10 %}hidden-tag{% endif %}" data-tag-index="{{ loop.index }}">
|
||||
<span>
|
||||
{% if 'Chat' in tag.name or 'GPT' in tag.name or '对话' in tag.name %}💬
|
||||
{% elif 'Image' in tag.name or '图' in tag.name %}🖼️
|
||||
{% elif 'Video' in tag.name or '视频' in tag.name %}🎬
|
||||
{% elif 'Writing' in tag.name or '写作' in tag.name %}✍️
|
||||
{% elif 'Coding' in tag.name or '代码' in tag.name %}💻
|
||||
{% elif 'Audio' in tag.name or '音频' in tag.name %}🎵
|
||||
{% elif '3D' in tag.name %}🎨
|
||||
{% else %}🏷️{% endif %}
|
||||
</span>
|
||||
{{ tag.name }}
|
||||
<span class="tag-count">{{ tag_counts.get(tag.id, 0) }}</span>
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% if tags|length > 10 %}
|
||||
<div class="more-tags-btn" id="moreTagsBtn">
|
||||
<span>更多</span>
|
||||
<span class="expand-icon">▼</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -313,7 +385,7 @@
|
||||
{% if search_query %}
|
||||
<div style="margin-bottom: 24px; padding: 16px; background: #f1f5f9; border-radius: 8px;">
|
||||
<p style="margin: 0; color: #64748b; font-size: 14px;">
|
||||
<span class="material-symbols-outlined" style="font-size: 18px; vertical-align: middle;">search</span>
|
||||
<span style="font-size: 18px; vertical-align: middle;">🔍</span>
|
||||
搜索 "{{ search_query }}" 的结果:找到 {{ pagination.total if pagination else sites|length }} 个工具
|
||||
<a href="/" style="margin-left: 12px; color: #0ea5e9; text-decoration: none;">清除搜索</a>
|
||||
</p>
|
||||
@@ -329,7 +401,7 @@
|
||||
{% else %}
|
||||
<div class="tool-logo" style="background: linear-gradient(135deg, #0ea5e9 0%, #8b5cf6 100%);"></div>
|
||||
{% endif %}
|
||||
<span class="material-symbols-outlined tool-link-icon">north_east</span>
|
||||
<span class="tool-link-icon">↗</span>
|
||||
</div>
|
||||
<h3 class="tool-name">{{ site.name }}</h3>
|
||||
<p class="tool-description">{{ site.short_desc or site.description }}</p>
|
||||
@@ -340,7 +412,7 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="tool-views">
|
||||
<span class="material-symbols-outlined">visibility</span>
|
||||
<span>👁</span>
|
||||
<span>{% if site.view_count >= 1000 %}{{ (site.view_count / 1000) | round(1) }}k{% else %}{{ site.view_count | default(0) }}{% endif %}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -354,11 +426,11 @@
|
||||
<!-- 上一页 -->
|
||||
{% if pagination.has_prev %}
|
||||
<a href="?page={{ pagination.prev_num }}{% if selected_tag %}&tag={{ selected_tag.slug }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}">
|
||||
<span class="material-symbols-outlined">chevron_left</span>
|
||||
<span>◀</span>
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="#" class="disabled">
|
||||
<span class="material-symbols-outlined">chevron_left</span>
|
||||
<span>◀</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
@@ -391,22 +463,52 @@
|
||||
<!-- 下一页 -->
|
||||
{% if pagination.has_next %}
|
||||
<a href="?page={{ pagination.next_num }}{% if selected_tag %}&tag={{ selected_tag.slug }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}">
|
||||
<span class="material-symbols-outlined">chevron_right</span>
|
||||
<span>▶</span>
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="#" class="disabled">
|
||||
<span class="material-symbols-outlined">chevron_right</span>
|
||||
<span>▶</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="empty-state">
|
||||
<span class="material-symbols-outlined">search_off</span>
|
||||
<span class="icon">🔍</span>
|
||||
<h3>暂无工具</h3>
|
||||
<p>{% if selected_tag %}该分类下还没有工具{% else %}还没有添加任何工具{% endif %}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 标签展开/收起功能
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const moreTagsBtn = document.getElementById('moreTagsBtn');
|
||||
if (moreTagsBtn) {
|
||||
moreTagsBtn.addEventListener('click', function() {
|
||||
const categoryTabs = document.getElementById('categoryTabs');
|
||||
const hiddenTags = categoryTabs.querySelectorAll('.hidden-tag');
|
||||
const isExpanded = moreTagsBtn.classList.contains('expanded');
|
||||
|
||||
if (isExpanded) {
|
||||
// 收起
|
||||
hiddenTags.forEach(tag => {
|
||||
tag.style.display = 'none';
|
||||
});
|
||||
moreTagsBtn.classList.remove('expanded');
|
||||
moreTagsBtn.querySelector('span:first-child').textContent = '更多';
|
||||
} else {
|
||||
// 展开
|
||||
hiddenTags.forEach(tag => {
|
||||
tag.style.display = 'inline-flex';
|
||||
});
|
||||
moreTagsBtn.classList.add('expanded');
|
||||
moreTagsBtn.querySelector('span:first-child').textContent = '收起';
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user