feat: add admin dashboard, pipeline service, lightbox, and update dependencies

This commit is contained in:
2026-06-09 09:32:10 +08:00
parent 0d293422ac
commit 32978b3fc5
50 changed files with 4054 additions and 1618 deletions
+44 -7
View File
@@ -1,15 +1,45 @@
{# 论文卡片组件 — paper 变量必须在上下文中 #}
<article class="paper-card" data-arxiv="{{ paper.arxiv_id }}">
{# 论文卡片组件 — 支持普通和搜索两种模式 #}
{% macro render_card(paper, snippets=None, distances=None, variant="default") %}
<article class="paper-card {% if variant == 'search' %}search-result{% endif %}"
data-arxiv="{{ paper.arxiv_id }}">
<div class="paper-card-header">
<h2 class="paper-title">
<a href="/paper/{{ paper.arxiv_id }}">
{{ paper.title_zh or paper.title_en }}
{% if variant == 'search' and snippets %}
{% set snip = snippets.get(paper.id, {}) %}
{% if snip and snip.title_zh %}
{{ snip.title_zh | safe }}
{% elif paper.title_zh %}
{{ paper.title_zh }}
{% else %}
{{ paper.title_en }}
{% endif %}
{% else %}
{{ paper.title_zh or paper.title_en }}
{% endif %}
</a>
</h2>
<span class="paper-upvotes">👍 {{ paper.upvotes }}</span>
{% if variant == 'search' and distances and paper.arxiv_id in distances %}
<span class="similarity-score" title="语义相似度距离">
🎯 {{ "%.3f"|format(distances[paper.arxiv_id]) }}
</span>
{% endif %}
</div>
{% if paper.summary and paper.summary.one_line %}
{% if variant == 'search' and snippets %}
{% set snip = snippets.get(paper.id, {}) %}
{% if snip and snip.abstract %}
<p class="paper-snippet">{{ snip.abstract | safe }}</p>
{% elif paper.summary and paper.summary.one_line %}
<p class="paper-one-line">{{ paper.summary.one_line }}</p>
{% elif paper.abstract %}
<p class="paper-abstract-preview">
{{ paper.abstract[:200] }}{% if paper.abstract|length > 200 %}…{% endif %}
</p>
{% endif %}
{% elif paper.summary and paper.summary.one_line %}
<p class="paper-one-line">{{ paper.summary.one_line }}</p>
{% elif paper.abstract %}
<p class="paper-abstract-preview">
@@ -21,6 +51,9 @@
<span class="paper-authors">
{{ paper.authors|map(attribute='name')|join(', ')|truncate(80) }}
</span>
{% if variant == 'search' %}
<span class="paper-date">{{ paper.paper_date }}</span>
{% endif %}
</div>
<div class="paper-tags">
@@ -39,14 +72,14 @@
未总结
{% elif paper.summary_status.status == 'processing' %}
🔄 总结中
{% elif paper.summary_status.status == 'failed' or paper.summary_status.status == 'permanent_failure' %}
{% elif paper.summary_status.status in ('failed', 'permanent_failure') %}
❌ 总结失败
{% elif paper.summary_status.status == 'done' %}
✅ 已总结
{% endif %}
{# djlint:on #}
</span>
{% if paper.reading_status %}
{% if paper.reading_status and variant != 'search' %}
<span class="reading-badge reading-{{ paper.reading_status.status }}">
{# djlint:off #}
{% if paper.reading_status.status == 'unread' %}
@@ -63,6 +96,7 @@
{% endif %}
</div>
<div class="paper-footer-right">
{% if variant != 'search' %}
<button
class="btn-bookmark {% if paper.bookmark %}active{% endif %}"
hx-post="/api/bookmark/{{ paper.arxiv_id }}"
@@ -71,9 +105,12 @@
>
{% if paper.bookmark %}★{% else %}☆{% endif %}
</button>
{% endif %}
<a href="/paper/{{ paper.arxiv_id }}" class="btn-detail">详情 →</a>
</div>
</div>
{# HTMX 刷新锚点 — button swap 替换此 div #}
{% if variant != 'search' %}
<span id="user-data-{{ paper.arxiv_id }}"></span>
{% endif %}
</article>
{% endmacro %}