ATRI风格模板 (#154)

* Add files via upload

* Create test

* Add files via upload

* Delete src/infrastructure/reporting/templates/ATRI/test

* Add files via upload
This commit is contained in:
凉雨
2026-04-03 13:51:10 +08:00
committed by GitHub
parent 5dd7cf1aa1
commit a5c3aa2af1
9 changed files with 5861 additions and 0 deletions
+1
View File
@@ -67,6 +67,7 @@
"type": "string",
"description": "报告模板",
"options": [
"ATRI",
"scrapbook",
"retro_futurism",
"HatsuneMiku",
@@ -0,0 +1,53 @@
<div class="chart-container">
<div style="display: flex; align-items: stretch; height: 220px; gap: 5px; padding: 20px 0 10px;">
{% for hour_data in chart_data %}
{% set ratio = loop.index0 / ((chart_data|length - 1) if (chart_data|length - 1) > 0 else 1) %}
{% if ratio < 0.3333 %}
{% set local_ratio = ratio / 0.3333 %}
{% set top_red = (210 + local_ratio * 45)|round|int %}
{% set top_green = (225 + local_ratio * 15)|round|int %}
{% set top_blue = (255 - local_ratio * 25)|round|int %}
{% set bottom_red = (170 + local_ratio * 85)|round|int %}
{% set bottom_green = (190 - local_ratio * 5)|round|int %}
{% set bottom_blue = (255 - local_ratio * 55)|round|int %}
{% elif ratio < 0.6666 %}
{% set local_ratio = (ratio - 0.3333) / 0.3333 %}
{% set top_red = (255 - local_ratio * 20)|round|int %}
{% set top_green = (240 + local_ratio * 15)|round|int %}
{% set top_blue = (230 + local_ratio * 10)|round|int %}
{% set bottom_red = (255 - local_ratio * 105)|round|int %}
{% set bottom_green = (185 + local_ratio * 45)|round|int %}
{% set bottom_blue = 200 %}
{% else %}
{% set local_ratio = (ratio - 0.6666) / 0.3334 %}
{% set top_red = (235 - local_ratio * 25)|round|int %}
{% set top_green = (255 - local_ratio * 30)|round|int %}
{% set top_blue = (240 + local_ratio * 15)|round|int %}
{% set bottom_red = (150 + local_ratio * 20)|round|int %}
{% set bottom_green = (230 - local_ratio * 40)|round|int %}
{% set bottom_blue = (200 + local_ratio * 55)|round|int %}
{% endif %}
{% set count_red = (bottom_red * 0.7)|round|int %}
{% set count_green = (bottom_green * 0.7)|round|int %}
{% set count_blue = (bottom_blue * 0.7)|round|int %} <div
style="flex: 1; display: flex; flex-direction: column; align-items: center; min-width: 0; height: 100%;">
<div
style="flex: 1; width: 100%; display: flex; flex-direction: column; align-items: center; justify-content: end;">
<span
style="font-size: 10px; font-weight: 700; color: rgb({{ count_red }}, {{ count_green }}, {{ count_blue }}); margin-bottom: 4px; line-height: 1; white-space: nowrap; text-shadow: 0 1px 0 rgba(255,255,255,0.65);">{{hour_data.count}}</span>
<div style="
background: linear-gradient(180deg, rgb({{ top_red }}, {{ top_green }}, {{ top_blue }}) 0%, rgb({{ bottom_red }}, {{ bottom_green }}, {{ bottom_blue }}) 100%);
width: calc(100% - 4px);
height: {{hour_data.percentage}}%;
border-radius: 10px 10px 0 0;
transition: all 0.3s ease;
min-height: 5px;
box-shadow: 0 6px 14px rgba({{ bottom_red }}, {{ bottom_green }}, {{ bottom_blue }}, 0.14);
border: none;
" title="{{hour_data.hour}}时 - {{hour_data.count}}条消息"></div>
</div>
<span style="font-size: 10px; color: #9a8aa3; margin-top: 8px; line-height: 1;">{{hour_data.hour}}</span>
</div>
{% endfor %}
</div>
</div>
@@ -0,0 +1,155 @@
<style>
.quality-card {
position: relative;
padding: 24px 24px 20px;
border-radius: 24px;
background: linear-gradient(90deg, rgba(255,240,230,0.95) 0%, rgba(255,255,255,0.98) 100%) !important;
border: 1px solid rgba(112, 189, 236, 0.22);
box-shadow: 0 18px 40px rgba(86, 161, 205, 0.14);
overflow: hidden;
}
.quality-card::before {
content: "锐评";
position: absolute;
top: 14px;
right: 18px;
font-size: 46px;
font-weight: 700;
color: rgba(83, 171, 219, 0.08);
letter-spacing: 4px;
}
.quality-head {
display: flex;
justify-content: space-between;
align-items: flex-end;
gap: 16px;
margin-bottom: 18px;
position: relative;
z-index: 1;
}
.quality-title {
font-size: 28px;
font-weight: 700;
color: #2a6587;
margin-bottom: 4px;
}
.quality-subtitle {
display: inline-flex;
align-items: center;
padding: 7px 12px;
border-radius: 999px;
background: rgba(117, 203, 244, 0.16);
color: #5492b7;
font-size: 14px;
}
.quality-bars {
display: grid;
gap: 12px;
margin-bottom: 16px;
position: relative;
z-index: 1;
}
.quality-bar-row {
display: grid;
grid-template-columns: 94px 1fr 54px;
align-items: center;
gap: 12px;
}
.quality-bar-label {
font-size: 14px;
color: #52768d;
font-weight: 600;
}
.quality-bar-track {
height: 12px;
border-radius: 999px;
background: rgba(126, 199, 235, 0.16);
overflow: hidden;
}
.quality-bar-fill {
height: 100%;
border-radius: 999px;
box-shadow: 0 6px 12px rgba(100, 167, 209, 0.2);
}
.quality-bar-value {
text-align: right;
font-size: 13px;
color: #5d88a3;
font-weight: 700;
}
.quality-comment-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
margin-bottom: 16px;
position: relative;
z-index: 1;
}
.quality-comment {
padding: 14px 14px 12px;
border-radius: 16px;
background: rgba(255,255,255,0.74);
border: 1px dashed rgba(113, 191, 237, 0.34);
}
.quality-comment strong {
display: inline-block;
margin-bottom: 6px;
color: #3f84ad;
}
.quality-summary {
position: relative;
z-index: 1;
padding: 14px 16px;
border-radius: 18px;
background: rgba(255, 255, 255, 0.65);
color: #4f7389;
line-height: 1.8;
border: 1px solid rgba(112, 189, 236, 0.2);
}
</style>
<div class="quality-card">
<div class="quality-head">
<div>
<div class="quality-title">{{ title }}</div>
<div class="quality-subtitle">{{ subtitle }}</div>
</div>
</div>
<div class="quality-bars">
{% for dim in dimensions %}
<div class="quality-bar-row">
<div class="quality-bar-label">{{ dim.name }}</div>
<div class="quality-bar-track">
<div class="quality-bar-fill" style="width: {{ dim.percentage }}%; background: linear-gradient(90deg, {{ dim.color }}, color-mix(in srgb, {{ dim.color }} 65%, white));"></div>
</div>
<div class="quality-bar-value">{{ dim.percentage }}%</div>
</div>
{% endfor %}
</div>
<div class="quality-comment-grid">
{% for dim in dimensions %}
<div class="quality-comment">
<strong>{{ dim.name }}</strong>
<div>{{ dim.comment }}</div>
</div>
{% endfor %}
</div>
<div class="quality-summary">{{ summary }}</div>
</div>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,569 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ATRI 群聊日报 · PDF版</title>
<style>
@page {
size: A4;
margin: 0;
}
@font-face {
font-family: 'LXGW WenKai';
src: url('https://c247c050.cloudflare-imgbed-37m.pages.dev/file/1774880718993_LXGWWenKai-Regular.woff2') format('woff2');
font-weight: 400;
}
@font-face {
font-family: 'LXGW WenKai';
src: url('https://c247c050.cloudflare-imgbed-37m.pages.dev/file/1774880715380_LXGWWenKai-Medium.woff2') format('woff2');
font-weight: 600;
}
@font-face {
font-family: 'LXGW WenKai Mono';
src: url('https://c247c050.cloudflare-imgbed-37m.pages.dev/file/1774880717027_LXGWWenKaiMono-Regular.woff2') format('woff2');
font-weight: 400;
}
:root {
--sky: #74c8f3;
--sea: #4ba9dc;
--deep: #27678f;
--foam: #eefaff;
--paper: #fffdf7;
--card: rgba(255, 255, 255, 0.82);
--card-soft: rgba(246, 251, 255, 0.9);
--border: rgba(103, 188, 237, 0.35);
--shadow: rgba(52, 126, 170, 0.14);
--text-main: #214861;
--text-sub: #638399;
--accent: #ffd56e;
--radius-xl: 28px;
--radius-lg: 22px;
--radius-md: 16px;
}
body {
font-family: 'LXGW WenKai', 'Microsoft YaHei', 'Arial', sans-serif;
margin: 0;
padding: 0;
background-color: #dff4ff;
background-image:
linear-gradient(180deg, rgba(255,255,255,0.82), rgba(242,251,255,0.95)),
linear-gradient(rgba(239, 250, 255, 0.72), rgba(239, 250, 255, 0.92)),
radial-gradient(circle at 15% 12%, rgba(255, 255, 255, 0.8), rgba(255,255,255,0) 26%),
linear-gradient(rgba(117, 193, 240, 0.08) 1px, transparent 1px),
linear-gradient(90deg, rgba(117, 193, 240, 0.08) 1px, transparent 1px),
url('https://c247c050.cloudflare-imgbed-37m.pages.dev/file/1774881257527_bg1.webp');
background-size: auto, auto, auto, 26px 26px, 26px 26px, cover;
color: var(--text-main);
line-height: 1.6;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
.container {
max-width: 190mm;
margin: 0 auto;
min-height: 297mm;
background: rgba(255,255,255,0.72);
border: 1px solid var(--border);
box-shadow: 0 24px 70px var(--shadow);
padding: 18mm 14mm 16mm;
position: relative;
overflow: hidden;
}
.container::before {
content: "";
position: absolute;
inset: 10mm;
border: 1px dashed rgba(103, 188, 237, 0.28);
border-radius: 18px;
pointer-events: none;
}
.container::after {
content: "ATRI";
position: absolute;
right: -8mm;
top: 6mm;
font-family: 'LXGW WenKai Mono', monospace;
font-size: 44mm;
letter-spacing: 2mm;
color: rgba(75, 169, 220, 0.07);
line-height: 1;
pointer-events: none;
}
.header {
position: relative;
margin-bottom: 10mm;
padding: 10mm 42mm 8mm 8mm;
border-radius: var(--radius-lg);
background:
linear-gradient(180deg, rgba(255,255,255,0.82), rgba(245,251,255,0.68)),
linear-gradient(135deg, rgba(137,205,243,0.08), rgba(255,255,255,0));
border: 1px solid var(--border);
box-shadow: 0 10px 30px rgba(75, 148, 196, 0.08);
overflow: hidden;
}
.header::before {
content: "";
position: absolute;
top: 5mm;
left: 8mm;
width: 24mm;
height: 6mm;
border-radius: 4px;
background: linear-gradient(180deg, rgba(255,255,255,0.66), rgba(235,248,255,0.34));
border: 1px solid rgba(170, 214, 239, 0.28);
opacity: 0.86;
}
.header::after {
content: "✦";
position: absolute;
right: 7mm;
top: 6mm;
font-size: 12pt;
color: rgba(92, 173, 217, 0.36);
}
.header h1 {
color: var(--text-main);
font-size: 24pt;
margin: 0;
font-weight: 600;
line-height: 1.25;
}
.header p {
color: var(--text-sub);
font-size: 11pt;
margin: 4mm 0 0 0;
font-family: 'LXGW WenKai Mono', monospace;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 4mm;
margin: 0 0 8mm 0;
}
.stat-card {
background: linear-gradient(180deg, rgba(255,255,255,0.78), rgba(248,252,255,0.64));
border-radius: var(--radius-md);
padding: 5mm 3mm;
text-align: center;
box-shadow: 0 8px 24px rgba(74, 145, 188, 0.08);
border: 1px solid var(--border);
}
.stat-value {
font-family: 'LXGW WenKai Mono', monospace;
font-size: 18pt;
font-weight: bold;
color: var(--sea);
margin-bottom: 2mm;
}
.stat-label {
color: var(--text-sub);
font-size: 10pt;
font-weight: 500;
}
.section {
margin: 0 0 8mm 0;
page-break-inside: avoid;
padding: 7mm;
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
position: relative;
overflow: hidden;
}
.section::before {
content: "";
position: absolute;
left: 7mm;
top: 4mm;
width: 22mm;
height: 5mm;
border-radius: 4px;
background: linear-gradient(180deg, rgba(255,252,240,0.9), rgba(238,248,255,0.48));
opacity: 0.88;
}
.section-title {
color: var(--text-main);
font-size: 16pt;
margin: 0 0 5mm 0;
padding-bottom: 3mm;
border-bottom: 1px solid rgba(103, 188, 237, 0.28);
font-weight: 600;
}
.chart-container {
background: var(--card-soft);
border-radius: var(--radius-md);
padding: 6mm;
margin: 4mm 0;
border: 1px solid rgba(103, 188, 237, 0.2);
}
.items-list {
list-style: none;
padding: 0;
}
.item {
background: linear-gradient(180deg, rgba(255,255,255,0.86), rgba(246,251,255,0.74));
margin: 4mm 0;
padding: 5mm;
border-radius: 12px;
border: 1px solid var(--border);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.04);
}
.item-title {
font-weight: bold;
color: var(--sea);
font-size: 11pt;
margin-bottom: 2mm;
}
.item-content {
color: var(--text-main);
line-height: 1.5;
font-size: 10pt;
}
.hero-summary {
display: grid;
grid-template-columns: 1.5fr 1fr;
gap: 6mm;
margin-bottom: 8mm;
page-break-inside: avoid;
}
.hero-card,
.peak-card {
position: relative;
border-radius: var(--radius-lg);
border: 1px solid var(--border);
background: var(--card);
padding: 7mm;
overflow: hidden;
}
.hero-card {
min-height: 42mm;
}
.hero-label,
.peak-caption {
display: inline-flex;
align-items: center;
padding: 2mm 4mm;
border-radius: 999px;
background: rgba(116, 200, 243, 0.14);
color: var(--deep);
font-size: 9pt;
letter-spacing: 0.5px;
margin-bottom: 3mm;
}
.hero-title {
margin: 0 0 3mm 0;
font-size: 18pt;
line-height: 1.3;
color: var(--text-main);
}
.hero-desc {
color: var(--text-sub);
font-size: 10.5pt;
line-height: 1.75;
max-width: 100%;
}
.peak-date-subtitle {
font-size: 9pt;
color: var(--text-sub);
margin-bottom: 2mm;
font-family: 'LXGW WenKai Mono', monospace;
}
.peak-time {
font-family: 'LXGW WenKai Mono', monospace;
font-size: 20pt;
color: var(--text-main);
font-weight: 600;
margin-bottom: 3mm;
white-space: nowrap;
}
.peak-note {
font-size: 12pt;
line-height: 1.8;
color: var(--text-main);
}
.token-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 4mm;
}
.token-box {
border-radius: 12px;
border: 1px solid rgba(103, 188, 237, 0.2);
background: linear-gradient(180deg, rgba(255,255,255,0.86), rgba(246,251,255,0.74));
padding: 4mm;
text-align: center;
}
.token-box strong {
display: block;
color: var(--sea);
margin-bottom: 2mm;
font-size: 10pt;
}
.quote-wrapper {
display: flex;
flex-direction: column;
width: 100%;
margin-bottom: 5mm;
position: relative;
page-break-inside: avoid;
}
.q-flex-container {
display: flex;
gap: 3mm;
align-items: flex-start;
}
.q-user-col {
display: flex;
flex-direction: column;
align-items: center;
flex-shrink: 0;
width: 12mm;
}
.q-avatar-box {
position: relative;
margin-bottom: 1mm;
}
.q-avatar {
width: 12mm;
height: 12mm;
border-radius: 50%;
border: 2px solid #fff;
background: #fff;
object-fit: cover;
box-shadow: 0 4px 10px rgba(91, 160, 201, 0.16);
}
.quote-wrapper:nth-child(odd) .q-avatar {
box-shadow: 0 0 0 1px var(--sky);
}
.quote-wrapper:nth-child(even) .q-avatar {
box-shadow: 0 0 0 1px var(--accent);
}
.q-content-col {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0;
align-items: flex-start;
}
.q-sender-name {
font-size: 10pt;
color: var(--text-sub);
margin-bottom: 2mm;
margin-left: 2mm;
}
.quote-wrapper:nth-child(even) .q-flex-container {
flex-direction: row-reverse;
}
.quote-wrapper:nth-child(even) .q-content-col {
align-items: flex-end;
}
.quote-wrapper:nth-child(even) .q-sender-name {
margin-left: 0;
margin-right: 2mm;
}
.q-bubble-wrap {
display: flex;
align-items: flex-end;
gap: 2mm;
max-width: 100%;
}
.quote-wrapper:nth-child(even) .q-bubble-wrap {
flex-direction: row-reverse;
}
.q-bubble {
background: rgba(255, 255, 255, 0.95);
border: 1px solid var(--border);
padding: 3mm 4mm;
border-radius: 6mm;
box-shadow: 0 4px 12px rgba(74, 145, 188, 0.08);
position: relative;
width: fit-content;
border-top-left-radius: 1mm;
}
.quote-wrapper:nth-child(even) .q-bubble {
border-top-left-radius: 6mm;
border-top-right-radius: 1mm;
background: rgba(238, 250, 255, 0.95);
}
.q-content {
font-size: 10.5pt;
line-height: 1.6;
color: var(--text-main);
word-break: break-word;
}
.q-analysis-note {
background: rgba(255, 253, 247, 0.9);
padding: 2mm 3mm;
font-size: 9pt;
color: var(--text-sub);
width: fit-content;
max-width: 85%;
margin-top: 2mm;
box-shadow: 0 2px 8px rgba(74, 145, 188, 0.05);
border: 1px solid rgba(117,193,240,0.15);
border-radius: 4mm;
border-top-left-radius: 1mm;
line-height: 1.5;
}
.quote-wrapper:nth-child(even) .q-analysis-note {
background: rgba(255, 249, 230, 0.9);
border-top-left-radius: 4mm;
border-top-right-radius: 1mm;
text-align: right;
}
.note-label {
font-weight: 600;
color: var(--sea);
margin-right: 1mm;
}
.quote-floating-emoji {
display: none;
}
.footer {
text-align: center;
margin-top: 10mm;
padding-top: 6mm;
border-top: 1px solid rgba(103, 188, 237, 0.24);
color: var(--text-sub);
font-size: 9pt;
}
@media print {
body {
background: #dff4ff;
}
.container {
box-shadow: none;
}
.stat-card {
break-inside: avoid;
}
.section {
break-inside: avoid;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>ATRI 群聊日报 · {{ current_date }}</h1>
<p>{{current_datetime}}</p>
</div>
<div class="hero-summary">
<div class="hero-card">
<div class="hero-label">今日群聊概览</div>
<h2 class="hero-title">今天的聊天像夏日的海风,温柔又热闹。</h2>
<div class="hero-desc">
今天共有 <strong>{{ message_count }}</strong> 条消息,来自 <strong>{{ participant_count }}</strong> 位成员。我已经把这些温暖的对话整理好了,揉进这份属于你们的日报里。
</div>
</div>
<div class="peak-card">
<div class="peak-caption">MOST ACTIVE PERIOD</div>
<div class="peak-date-subtitle">{{ current_datetime }}</div>
<div class="peak-time">{{ most_active_period }}</div>
<div class="peak-note">这段时间的讨论最集中,像潮水推到岸边一样热烈,是今天群聊最明亮的一段波峰。</div>
</div>
</div>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value">{{message_count}}</div>
<div class="stat-label">总消息数</div>
</div>
<div class="stat-card">
<div class="stat-value">{{participant_count}}</div>
<div class="stat-label">参与人数</div>
</div>
<div class="stat-card">
<div class="stat-value">{{total_characters}}</div>
<div class="stat-label">总字符数</div>
</div>
<div class="stat-card">
<div class="stat-value">{{emoji_count}}</div>
<div class="stat-label">表情数量</div>
</div>
</div>
<div class="section">
<h2 class="section-title">活跃潮汐</h2>
<div class="chart-container">
{{hourly_chart_html}}
</div>
</div>
<div class="section">
<h2 class="section-title">热门话题</h2>
<ul class="items-list">
{{topics_html | safe}}
</ul>
</div>
<div class="section">
<h2 class="section-title">今日称号</h2>
<ul class="items-list">
{{titles_html | safe}}
</ul>
</div>
<div class="section">
<h2 class="section-title">今日金句</h2>
<div class="html-slot">
{{quotes_html | safe}}
</div>
</div>
<div class="section">
<h2 class="section-title">Token 统计</h2>
<div class="chart-container">
<div class="token-grid">
<div class="token-box">
<strong>总消耗</strong>
{{total_tokens}} tokens
</div>
<div class="token-box">
<strong>提示词 Token</strong>
{{prompt_tokens}} tokens
</div>
<div class="token-box">
<strong>生成内容 Token</strong>
{{completion_tokens}} tokens
</div>
</div>
</div>
</div>
<div class="footer">
<p>Generated by AstrBot Daily Analysis Plugin</p>
<p>ATRI · PDF 模式适配完成</p>
</div>
</div>
</body>
</html>
@@ -0,0 +1,33 @@
{% set quote_emojis = [
'https://tc.ciallo.ccwu.cc/file/1775132814629_1774881270686_爱心.gif',
'https://tc.ciallo.ccwu.cc/file/1775132815504_1774881268554_可爱.gif',
'https://tc.ciallo.ccwu.cc/file/1775132809943_1774881264350_睡觉.gif',
'https://tc.ciallo.ccwu.cc/file/1775175892953_1774881267664_舔屏幕.gif'
] %}
{% for quote in quotes %}
<div class="quote-wrapper">
<div class="q-flex-container">
<div class="q-user-col">
{% if quote.avatar_url %}
<div class="q-avatar-box">
<img src="{{ quote.avatar_url }}" class="q-avatar">
</div>
{% endif %}
</div>
<div class="q-content-col">
<div class="q-sender-name">{{ quote.sender }}</div>
<div class="q-bubble-wrap">
<div class="q-bubble">
<div class="q-content">{{ quote.content }}</div>
</div>
<img class="quote-floating-emoji" src="{{ quote_emojis | random }}" alt="金句表情">
</div>
<div class="q-analysis-note">
<span class="note-label">📝 亚托莉的高性能分析:</span>
{{ quote.reason | safe }}
</div>
</div>
</div>
</div>
{% endfor %}
@@ -0,0 +1,44 @@
{% set topic_emojis = [
'https://tc.ciallo.ccwu.cc/file/1775132804506_1774881263342_观察.gif',
'https://tc.ciallo.ccwu.cc/file/1775132805081_1774881262835_疑惑.gif',
'https://tc.ciallo.ccwu.cc/file/1775132815504_1774881268554_可爱.gif',
'https://tc.ciallo.ccwu.cc/file/1775132817115_1774881269400_可爱-1.gif',
'https://tc.ciallo.ccwu.cc/file/1775132805485_1774881263748_可爱-3.gif'
] %}
{% set topic_rank_colors = [
{'bg': 'linear-gradient(135deg, #a9d8ff 0%, #8fc5ff 48%, #8aaeff 100%)', 'text': '#ffffff', 'shadow': 'rgba(126, 177,
255, 0.34)', 'border': 'rgba(255, 255, 255, 0.82)'},
{'bg': 'linear-gradient(135deg, #ffc8d8 0%, #ffb7cd 50%, #ffb2b2 100%)', 'text': '#ffffff', 'shadow': 'rgba(255, 176,
204, 0.32)', 'border': 'rgba(255, 255, 255, 0.8)'},
{'bg': 'linear-gradient(135deg, #ffe0ad 0%, #ffd29f 46%, #ffc3b8 100%)', 'text': '#ffffff', 'shadow': 'rgba(255, 199,
142, 0.3)', 'border': 'rgba(255, 255, 255, 0.8)'},
{'bg': 'linear-gradient(135deg, #c7efe7 0%, #bfe7ff 52%, #c8d8ff 100%)', 'text': '#ffffff', 'shadow': 'rgba(163, 221,
230, 0.28)', 'border': 'rgba(255, 255, 255, 0.8)'}
] %}
{% for topic in topics %}
{% set rank = topic_rank_colors[loop.index0 % (topic_rank_colors|length)] %}
<li class="item item-with-emoji">
<div class="item-main">
<div class="item-title">
<span
style="display: inline-flex; align-items: center; justify-content: center; min-width: 38px; height: 26px; padding: 0 10px; margin-right: 8px; border-radius: 999px; font-size: 0.78em; font-weight: 800; letter-spacing: 0.2px; color: {{ rank.text }}; background: {{ rank.bg }}; border: 1px solid {{ rank.border }}; box-shadow: 0 7px 16px {{ rank.shadow }}, inset 0 1px 0 rgba(255,255,255,0.45); vertical-align: middle;">
#{{ topic.index }}
</span>
{{ topic.topic.topic }}
</div>
<div class="item-content">
{% if topic.topic.count is defined %}
<p><strong>讨论热度:</strong> {{ topic.topic.count }} 次提及</p>
{% endif %}
<p><strong>参与的群友:</strong> {{ topic.contributors }}</p>
{% if topic.detail %}
<div
style="margin-top: 8px; padding: 12px 18px; background: linear-gradient(180deg, rgba(245,250,255,0.95), rgba(236,247,255,0.88)); border-radius: 16px; border: 1.5px solid rgba(255, 255, 255, 0.8); box-shadow: 0 4px 12px rgba(85,126,169,0.03); color: var(--text-main); line-height: 1.6;">
{{ topic.detail | safe }}
</div>
{% endif %}
</div>
</div>
<img class="item-emoji topic-emoji" src="{{ topic_emojis | random }}" alt="话题表情">
</li>
{% endfor %}
@@ -0,0 +1,39 @@
{% set title_emojis = [
'https://tc.ciallo.ccwu.cc/file/1775132813334_1774881267181_得意.gif',
'https://tc.ciallo.ccwu.cc/file/1775132808652_1774881267385_得意-1.gif',
'https://tc.ciallo.ccwu.cc/file/1775132804506_1774881263342_观察.gif',
'https://tc.ciallo.ccwu.cc/file/1775132811492_1774881264336_不要.gif'
] %}
{% set title_badge_colors = [
{'bg': 'linear-gradient(135deg, #ffcadf 0%, #ffc1cc 45%, #ffd9b8 100%)', 'text': '#b85c7b', 'shadow': 'rgba(255, 177, 203, 0.28)', 'border': 'rgba(255, 184, 210, 0.72)'},
{'bg': 'linear-gradient(135deg, #bfe7ff 0%, #c8dbff 48%, #d8ccff 100%)', 'text': '#5d71b8', 'shadow': 'rgba(168, 198, 255, 0.26)', 'border': 'rgba(173, 204, 255, 0.74)'},
{'bg': 'linear-gradient(135deg, #c7f3df 0%, #d3f1ff 50%, #e1ddff 100%)', 'text': '#4e8e88', 'shadow': 'rgba(161, 232, 205, 0.24)', 'border': 'rgba(178, 230, 214, 0.72)'},
{'bg': 'linear-gradient(135deg, #ffe5b7 0%, #ffd6c7 48%, #ffd7ef 100%)', 'text': '#b57752', 'shadow': 'rgba(255, 210, 163, 0.28)', 'border': 'rgba(255, 214, 178, 0.76)'}
] %}
{% for title in titles %}
{% set badge = title_badge_colors[loop.index0 % (title_badge_colors|length)] %}
<li class="item item-with-emoji">
<div class="item-main">
<div style="display: flex; align-items: center; gap: 15px;">
{% if title.avatar_data %}
<img src="{{ title.avatar_data }}"
alt="头像"
style="width: 50px; height: 50px; border-radius: 50%; object-fit: cover; border: 2px solid #667eea;">
{% endif %}
<div style="flex: 1;">
<div class="item-title">
{{ title.name }}
<span style="display: inline-flex; align-items: center; margin-left: 10px; padding: 5px 10px; border-radius: 999px; font-size: 0.78em; font-weight: 700; letter-spacing: 0.2px; color: {{ badge.text }}; background: {{ badge.bg }}; border: 1px solid {{ badge.border }}; box-shadow: 0 6px 14px {{ badge.shadow }}, inset 0 1px 0 rgba(255,255,255,0.55); vertical-align: middle;">
{{ title.title }}
</span>
</div>
<div class="item-content">
<p><strong>MBTI:</strong> {{ title.mbti }}</p>
<p><strong>称号理由:</strong> {{ title.reason }}</p>
</div>
</div>
</div>
</div>
<img class="item-emoji title-emoji" src="{{ title_emojis | random }}" alt="称号表情">
</li>
{% endfor %}