feat: 使用 Pencil 优化首页 UI

This commit is contained in:
meijiali
2026-07-07 17:27:23 +08:00
parent 74b4e606fa
commit c22556430e
3 changed files with 156 additions and 11 deletions
+124
View File
@@ -146,6 +146,18 @@ a {
padding: 30px;
}
.hero-band-inverse {
background: #111827;
border-color: #111827;
border-radius: 0;
box-shadow: none;
color: #ffffff;
margin-left: calc(50% - 50vw);
margin-right: calc(50% - 50vw);
margin-top: -1.5rem;
padding: 42px max(48px, calc((100vw - 1180px) / 2 + 24px));
}
.hero-shell {
align-items: flex-end;
display: flex;
@@ -166,6 +178,12 @@ a {
margin: 0 0 12px;
}
.hero-band-inverse .hero-copy h1 {
color: #ffffff;
font-size: 42px;
max-width: 720px;
}
.hero-copy p:not(.eyebrow) {
color: var(--muted-foreground);
font-size: 15px;
@@ -173,6 +191,16 @@ a {
margin: 0;
}
.hero-band-inverse .eyebrow {
color: #9ca3af;
font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
}
.hero-band-inverse .hero-copy p:not(.eyebrow) {
color: #d1d5db;
max-width: 680px;
}
.hero-metrics {
display: grid;
gap: 10px;
@@ -180,6 +208,13 @@ a {
min-width: 320px;
}
.hero-data-grid {
border: 1px solid #374151;
gap: 0;
grid-template-columns: repeat(3, minmax(120px, 1fr));
min-width: 420px;
}
.hero-metric {
background: var(--muted);
border: 1px solid var(--border);
@@ -187,12 +222,31 @@ a {
padding: 12px;
}
.hero-band-inverse .hero-metric {
background: transparent;
border: 0;
border-right: 1px solid #374151;
border-radius: 0;
padding: 18px 20px;
}
.hero-band-inverse .hero-metric:last-child {
border-right: 0;
}
.hero-metric strong {
display: block;
font-size: 18px;
line-height: 1.2;
}
.hero-band-inverse .hero-metric strong {
color: #ffffff;
font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
font-size: 30px;
font-weight: 700;
}
.hero-metric span {
color: var(--muted-foreground);
display: block;
@@ -200,6 +254,53 @@ a {
margin-top: 4px;
}
.hero-band-inverse .hero-metric span {
color: #9ca3af;
}
.task-workspace {
display: grid;
gap: 24px;
margin-top: 28px;
}
.hard-panel {
border-radius: 0;
box-shadow: none;
}
.panel-heading {
padding: 18px 24px;
}
.panel-note {
color: var(--muted-foreground);
font-size: 13px;
}
.scale-hint-panel {
border-top: 1px solid var(--border);
color: var(--muted-foreground);
font-size: 13px;
margin: 20px -20px -20px;
padding: 14px 20px;
}
.data-grid-table {
min-width: 1120px;
}
.data-grid-table thead th {
height: 48px;
padding-left: 16px;
padding-right: 16px;
}
.data-grid-table td {
padding-left: 16px;
padding-right: 16px;
}
.btn {
border-radius: 6px;
font-size: 14px;
@@ -496,6 +597,10 @@ a {
min-width: 0;
width: 100%;
}
.hero-data-grid {
min-width: 0;
}
}
@media (max-width: 768px) {
@@ -508,14 +613,33 @@ a {
padding: 22px;
}
.hero-band-inverse {
margin-left: -14px;
margin-right: -14px;
padding: 28px 22px;
}
.hero-copy h1 {
font-size: 28px;
}
.hero-band-inverse .hero-copy h1 {
font-size: 30px;
}
.hero-metrics {
grid-template-columns: 1fr;
}
.hero-band-inverse .hero-metric {
border-bottom: 1px solid #374151;
border-right: 0;
}
.hero-band-inverse .hero-metric:last-child {
border-bottom: 0;
}
.section-heading,
.page-heading,
.content-item-row {
+13 -11
View File
@@ -2,14 +2,14 @@
{% set has_running_tasks = tasks | selectattr("status", "equalto", "running") | list | length > 0 %}
{% block title %}热榜评论雷达 - 热榜评论分析工具{% endblock %}
{% block content %}
<section class="hero-band mb-4">
<section class="hero-band hero-band-inverse">
<div class="hero-shell">
<div class="hero-copy">
<p class="eyebrow">Hot Comment Radar</p>
<h1>热榜评论雷达</h1>
<p>从小红书和抖音热点出发,抓取真实评论,生成 AI 情绪、标签和可导出的分析报告</p>
<h1>抓取热点评论,快速看清讨论情绪</h1>
<p>面向内部演示和联调的轻量工具:选择平台、控制抓取规模、查看任务状态,并进入报告和评论明细</p>
</div>
<div class="hero-metrics" aria-label="默认任务规模">
<div class="hero-metrics hero-data-grid" aria-label="默认任务规模">
<div class="hero-metric">
<strong>5</strong>
<span>默认热点</span>
@@ -26,8 +26,9 @@
</div>
</section>
<section class="tool-card mb-4" id="create-task">
<div class="section-heading">
<div class="task-workspace">
<section class="tool-card hard-panel" id="create-task">
<div class="section-heading panel-heading">
<div>
<p class="section-kicker">采集配置</p>
<h2>创建抓取任务</h2>
@@ -61,23 +62,23 @@
<button class="btn btn-primary w-100" id="submit-btn" type="submit">开始抓取</button>
</div>
</div>
<div class="form-text text-muted mt-2" id="scale-hint">
<div class="scale-hint-panel" id="scale-hint">
预计最多抓取:<strong id="scale-calc">1250</strong> 条评论(实际数量可能受平台返回数量、去重、失败、限流影响)
</div>
</form>
</div>
</section>
<section class="tool-card" id="task-history">
<div class="section-heading">
<section class="tool-card hard-panel" id="task-history">
<div class="section-heading panel-heading">
<div>
<p class="section-kicker">任务历史</p>
<h2>最近任务</h2>
</div>
{% if has_running_tasks %}<span class="badge text-bg-warning">自动更新中</span>{% endif %}
<span class="panel-note">{% if has_running_tasks %}自动更新中{% else %}运行中任务自动刷新{% endif %}</span>
</div>
<div class="table-responsive">
<table class="table app-table align-middle mb-0">
<table class="table app-table data-grid-table align-middle mb-0">
<thead>
<tr>
<th>任务 ID</th>
@@ -95,6 +96,7 @@
</table>
</div>
</section>
</div>
{% if has_running_tasks %}
<script>document.addEventListener("DOMContentLoaded", () => pollTaskListStatus());</script>
{% endif %}
+19
View File
@@ -25,6 +25,25 @@ def test_index_page_renders_task_form_empty_state_and_default_scale():
assert "还没有任何任务" in response.text
def test_index_page_uses_pencil_data_grid_layout_for_ui_polish():
with make_test_client() as (client, _engine):
response = client.get("/")
assert response.status_code == 200
soup = BeautifulSoup(response.text, "html.parser")
visible_text = soup.get_text(" ")
hero = soup.select_one(".hero-band.hero-band-inverse")
assert hero is not None
assert "抓取热点评论,快速看清讨论情绪" in visible_text
assert soup.select_one(".hero-metrics.hero-data-grid") is not None
assert soup.select_one(".task-workspace") is not None
assert soup.select_one(".tool-card.hard-panel") is not None
assert soup.select_one(".section-heading.panel-heading") is not None
assert soup.select_one("table.app-table.data-grid-table") is not None
assert soup.select_one(".scale-hint-panel") is not None
assert "运行中任务自动刷新" in visible_text
def test_index_page_lists_existing_tasks():
with make_test_client() as (client, engine):
from sqlalchemy.orm import Session