增强 Gemini 总结模板资讯密度与统计展示

- 新增模板统计视图模型,接入消息总数/活跃人数/文本量/媒体量等核心指标\n- 追加深度统计卡片(Links/Emoji/Video/Sections/Bullets/Quotes/Code)并展示活跃等级\n- 从结构化章节提取话题雷达标签与核心看点,提升信息可读性\n- 调整模板为高信息密度布局,参考 gemini-code 风格进行 KPI、标签与双栏信息区展示\n- 模板模式下停止在正文拼接群概览与 tokens 文本,改由可视化卡片与页脚指标展示\n- 完善渲染链路参数传递:message_stats 与 metadata 全量传入模板渲染
This commit is contained in:
liuwei
2026-04-23 10:12:55 +08:00
parent dfe7d20e1e
commit 845b58ecc8
2 changed files with 627 additions and 116 deletions

View File

@@ -115,118 +115,106 @@
.meta-value.brand {
color: var(--brand);
}
.topic-radar {
margin-top: 12px;
}
.topic-tags {
margin-top: 6px;
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.topic-tag {
padding: 3px 8px;
border-radius: 999px;
font-size: 10px;
font-weight: 700;
color: #334155;
background: #f8fafc;
border: 1px solid #e2e8f0;
}
.summary-body {
padding: 18px 20px 20px;
}
.markdown-body {
.lead-callout {
margin-top: 10px;
padding: 10px 12px;
background: var(--ok-soft);
border-left: 2px solid var(--ok-line);
border-radius: 0 6px 6px 0;
font-size: 13px;
line-height: 1.86;
color: var(--text);
word-wrap: break-word;
line-height: 1.78;
color: #166534;
}
.markdown-body > *:first-child { margin-top: 0; }
.markdown-body > *:last-child { margin-bottom: 0; }
.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
color: var(--title);
margin: 16px 0 8px;
line-height: 1.42;
.sections {
margin-top: 12px;
display: flex;
flex-direction: column;
gap: 10px;
}
.section-card {
border: 1px solid #e5eaf1;
background: #ffffff;
border-radius: 8px;
padding: 10px 11px;
}
.section-title {
margin: 0 0 8px;
font-size: 14px;
font-weight: 800;
color: var(--title);
letter-spacing: -.01em;
}
.markdown-body h1 { font-size: 20px; border-bottom: 1px solid var(--line); padding-bottom: 6px; }
.markdown-body h2 { font-size: 18px; }
.markdown-body h3 { font-size: 16px; }
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 { font-size: 14px; }
.markdown-body p { margin: 10px 0; }
.markdown-body ul,
.markdown-body ol {
margin: 8px 0 12px;
padding-left: 18px;
.section-items {
display: flex;
flex-direction: column;
gap: 6px;
}
.markdown-body li { margin: 4px 0; }
.markdown-body blockquote {
margin: 10px 0;
.item-paragraph {
margin: 0;
font-size: 13px;
line-height: 1.82;
color: var(--text);
}
.item-bullet {
margin: 0;
padding-left: 14px;
position: relative;
font-size: 13px;
line-height: 1.78;
color: var(--text);
}
.item-bullet::before {
content: "•";
position: absolute;
left: 0;
top: 0;
color: var(--brand);
font-weight: 900;
}
.item-quote {
margin: 0;
padding: 8px 10px;
border-left: 3px solid var(--quote-line);
background: var(--quote-bg);
color: #475569;
border-radius: 0 4px 4px 0;
}
.markdown-body hr {
border: none;
border-top: 1px dashed #dbe3ee;
margin: 14px 0;
}
.markdown-body a {
color: var(--brand);
text-decoration: none;
border-bottom: 1px dotted rgba(37, 99, 235, .5);
}
.markdown-body strong {
color: #1e293b;
font-weight: 800;
}
.markdown-body em {
color: #475569;
font-style: italic;
}
.markdown-body code {
/* 说明:代码字体优先使用本地/系统等宽字体栈,保证服务端离线场景可读。 */
font-family: var(--abot-font-code, "Cascadia Mono", "Consolas", "SFMono-Regular", Menlo, monospace);
font-size: 12px;
background: #eff6ff;
color: #1e40af;
padding: 1px 4px;
border-radius: 4px;
line-height: 1.75;
}
.markdown-body pre {
margin: 10px 0;
.item-code {
margin: 0;
padding: 10px 11px;
border-radius: 6px;
background: var(--code-bg);
color: var(--code-text);
overflow-x: auto;
border: 1px solid #1e293b;
}
.markdown-body pre code {
background: transparent;
color: inherit;
padding: 0;
border-radius: 0;
/* 说明:代码字体优先使用本地/系统等宽字体栈,保证服务端离线场景可读。 */
font-family: var(--abot-font-code, "Cascadia Mono", "Consolas", "SFMono-Regular", Menlo, monospace);
font-size: 12px;
line-height: 1.7;
}
.markdown-body table {
width: 100%;
border-collapse: collapse;
margin: 10px 0;
font-size: 11px;
border: 1px solid #e2e8f0;
}
.markdown-body th,
.markdown-body td {
border: 1px solid #e2e8f0;
padding: 6px 7px;
text-align: left;
vertical-align: top;
}
.markdown-body th {
background: #f8fafc;
color: #334155;
font-weight: 700;
}
.markdown-body img {
max-width: 100%;
border-radius: 6px;
border: 1px solid #e2e8f0;
margin: 6px 0;
white-space: pre-wrap;
word-break: break-word;
}
.summary-footer {
margin-top: 14px;
@@ -255,6 +243,82 @@
font-size: 12px;
color: #166534;
}
.fallback-text {
margin-top: 10px;
font-size: 12px;
line-height: 1.76;
color: #475569;
white-space: pre-wrap;
}
.summary-grid {
display: grid;
grid-template-columns: 1.45fr 1fr;
gap: 10px;
margin-top: 12px;
}
.mini-card {
border: 1px solid #e5eaf1;
border-radius: 8px;
padding: 10px 11px;
background: #fff;
}
.mini-title {
margin: 0 0 8px;
font-size: 10px;
text-transform: uppercase;
letter-spacing: .08em;
color: #94a3b8;
font-weight: 800;
}
.mini-list {
display: flex;
flex-direction: column;
gap: 5px;
}
.mini-row {
display: flex;
justify-content: space-between;
align-items: center;
gap: 8px;
font-size: 12px;
color: #475569;
}
.mini-row .value {
font-weight: 800;
color: #1e293b;
font-family: var(--abot-font-code, "Cascadia Mono", "Consolas", monospace);
}
.highlight-list {
display: flex;
flex-direction: column;
gap: 6px;
}
.highlight-item {
margin: 0;
font-size: 12px;
line-height: 1.72;
color: #334155;
padding-left: 12px;
position: relative;
}
.highlight-item::before {
content: "";
position: absolute;
left: 0;
top: 7px;
width: 5px;
height: 5px;
border-radius: 50%;
background: #2563eb;
}
@media (max-width: 640px) {
.summary-grid {
grid-template-columns: 1fr;
}
.meta-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
</style>
</head>
<body>
@@ -265,39 +329,85 @@
<div class="header-title">CHAT INSIGHTS <span class="accent">SUMMARY</span></div>
<div class="header-id">{{ generated_at }}</div>
</div>
<div class="header-tag">Daily Archive</div>
<div class="header-tag">{{ summary_metrics.activity_badge or "Daily Archive" }}</div>
</div>
<div class="meta-grid">
{% for card in summary_metrics.kpi_cards %}
<div class="meta-item">
<span class="label-tiny">Type</span>
<div class="meta-value">群总结</div>
<span class="label-tiny">{{ card.label }}</span>
<div class="meta-value {% if card.tone == 'blue' %}brand{% endif %}">{{ card.value }}</div>
</div>
<div class="meta-item">
<span class="label-tiny">Mode</span>
<div class="meta-value brand">Template</div>
</div>
<div class="meta-item">
<span class="label-tiny">Render</span>
<div class="meta-value">HTML</div>
</div>
<div class="meta-item">
<span class="label-tiny">Engine</span>
<div class="meta-value">LLM</div>
{% endfor %}
</div>
<div class="topic-radar">
<span class="label-tiny"># Personal Interest Radar</span>
<div class="topic-tags">
{% for tag in summary_metrics.topic_tags %}
<span class="topic-tag">{{ tag }}</span>
{% endfor %}
{% if not summary_metrics.topic_tags %}
<span class="topic-tag">暂无热点标签</span>
{% endif %}
</div>
</div>
</header>
<section class="summary-body">
<span class="label-tiny"># {{ title }}</span>
<div class="markdown-body">
{{ summary_html }}
<span class="label-tiny"># {{ summary_doc_title or title }}</span>
<div class="lead-callout">
{{ summary_lead or "暂无总结内容。" }}
</div>
<div class="safe-callout">
内容已按 Markdown 富标签样式渲染(标题、列表、表格、代码块、引用)。
<div class="sections">
{% for section in summary_sections %}
<article class="section-card">
<h3 class="section-title">{{ section["title"] }}</h3>
<div class="section-items">
{% for item in section["items"] %}
{% if item["kind"] == "bullet" %}
<p class="item-bullet">{{ item["text"] }}</p>
{% elif item["kind"] == "quote" %}
<blockquote class="item-quote">{{ item["text"] }}</blockquote>
{% elif item["kind"] == "code" %}
<pre class="item-code">{{ item["text"] }}</pre>
{% else %}
<p class="item-paragraph">{{ item["text"] }}</p>
{% endif %}
{% endfor %}
</div>
</article>
{% endfor %}
</div>
{% if not summary_sections %}
<div class="fallback-text">{{ summary_fallback_text }}</div>
{% endif %}
<div class="summary-grid">
<div class="mini-card">
<h4 class="mini-title"># Deep Stats</h4>
<div class="mini-list">
{% for item in summary_metrics.mini_stats %}
<div class="mini-row">
<span>{{ item.label }}</span>
<span class="value">{{ item.value }}</span>
</div>
{% endfor %}
</div>
</div>
<div class="mini-card">
<h4 class="mini-title"># Core Highlights</h4>
<div class="highlight-list">
{% for text in summary_metrics.highlights %}
<p class="highlight-item">{{ text }}</p>
{% endfor %}
{% if not summary_metrics.highlights %}
<p class="highlight-item">暂无可提取的核心看点</p>
{% endif %}
</div>
</div>
</div>
<div class="safe-callout">内容已按结构化规则重排渲染,不再直接内嵌原始 HTML。</div>
<div class="summary-footer">
<span>ABOT · Message Summary Gemini Style</span>
<span class="right">Renderer: Playwright</span>
<span class="right">Tokens: {{ summary_metrics.token_total }} · Latency: {{ summary_metrics.latency_text }}</span>
</div>
</section>
</div>