feat: polish douyu active user cards

This commit is contained in:
liuwei
2026-04-08 14:36:05 +08:00
parent 41c8ce403c
commit b56822b196
2 changed files with 118 additions and 26 deletions

View File

@@ -1455,10 +1455,18 @@ class DouyuPlugin(MessagePluginInterface):
nickname = str(item.get("nickname") or item.get("uid") or "").strip()
msg_count = int(item.get("message_count", 0) or 0)
fans_name = str(item.get("fans_name") or "").strip()
fans_level = int(item.get("fans_level", 0) or 0)
room_level = int(item.get("room_level", 0) or 0)
tags = []
if fans_name:
core_parts.append(f"{nickname}{fans_name}{msg_count}条)")
else:
core_parts.append(f"{nickname}{msg_count}条)")
if fans_level > 0:
tags.append(f"{fans_name} Lv{fans_level}")
else:
tags.append(fans_name)
if room_level > 0:
tags.append(f"房间 Lv{room_level}")
tags.append(f"{msg_count}")
core_parts.append(f"{nickname}{''.join(tags)}")
if core_parts:
lines.append(f"- 核心发言用户:{''.join(core_parts)}")

View File

@@ -161,6 +161,35 @@ def _render_hot_times(peak_buckets: List[Dict[str, Any]]) -> str:
return "".join(blocks)
def _render_active_users(top_active_users: List[Dict[str, Any]]) -> str:
blocks = []
for item in top_active_users[:10]:
nickname = str(item.get("nickname") or item.get("uid") or "").strip()
fans_name = str(item.get("fans_name") or "").strip()
fans_level = int(item.get("fans_level", 0) or 0)
room_level = int(item.get("room_level", 0) or 0)
message_count = int(item.get("message_count", 0) or 0)
chips = []
if fans_name:
fans_label = f"{fans_name} Lv{fans_level}" if fans_level > 0 else fans_name
chips.append(f'<span class="user-chip fans">{_escape(fans_label)}</span>')
if room_level > 0:
chips.append(f'<span class="user-chip room">{_escape(f"房间 Lv{room_level}")}</span>')
meta_html = "".join(chips) if chips else '<span class="user-chip plain">普通观众</span>'
blocks.append(
'<div class="active-user-card">'
'<div class="active-user-top">'
f'<div class="active-user-name">{_escape(nickname)}</div>'
f'<div class="active-user-count">{_escape(message_count)}<span>条</span></div>'
'</div>'
f'<div class="active-user-meta">{meta_html}</div>'
'</div>'
)
return "".join(blocks)
def render_daily_report_html(
payload: Dict[str, Any],
danmu_summary: str,
@@ -183,15 +212,6 @@ def render_daily_report_html(
template_items = _build_template_items(payload)
top_active_users = payload.get("operator_metrics", {}).get("top_active_users", []) or []
active_user_items = []
for item in top_active_users[:10]:
nickname = str(item.get("nickname") or item.get("uid") or "").strip()
fans_name = str(item.get("fans_name") or "").strip()
message_count = int(item.get("message_count", 0) or 0)
if fans_name:
active_user_items.append(f"{nickname} | {fans_name} | {message_count}")
else:
active_user_items.append(f"{nickname} | {message_count}")
lead_summary, danmu_bullets = _split_summary_blocks(danmu_summary)
danmu_bullets = _normalize_summary_bullets(payload, danmu_bullets, target_count=5)
@@ -413,19 +433,6 @@ def render_daily_report_html(
line-height: 1.72;
font-size: 16px;
}}
.compact-user-list {{
margin: 0;
padding-left: 18px;
column-count: 2;
column-gap: 20px;
}}
.compact-user-list li {{
break-inside: avoid;
color: #475569;
margin: 8px 0;
line-height: 1.62;
font-size: 14px;
}}
.aside-card {{
padding: 18px;
border-radius: 20px;
@@ -465,6 +472,76 @@ def render_daily_report_html(
font-size: 12px;
color: #6b7280;
}}
.active-user-grid {{
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
}}
.active-user-card {{
padding: 14px 15px;
border-radius: 18px;
background: linear-gradient(180deg, rgba(255,255,255,0.96), rgba(244,247,255,0.92));
border: 1px solid rgba(129,147,181,0.18);
box-shadow: 0 10px 24px rgba(25, 38, 66, 0.05);
}}
.active-user-top {{
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
margin-bottom: 10px;
}}
.active-user-name {{
font-size: 16px;
font-weight: 700;
color: var(--navy);
line-height: 1.35;
word-break: break-all;
}}
.active-user-count {{
flex-shrink: 0;
min-width: 58px;
text-align: right;
font-size: 24px;
font-weight: 800;
color: var(--blue);
line-height: 1;
}}
.active-user-count span {{
margin-left: 2px;
font-size: 12px;
font-weight: 600;
color: #64748b;
}}
.active-user-meta {{
display: flex;
flex-wrap: wrap;
gap: 8px;
}}
.user-chip {{
display: inline-flex;
align-items: center;
padding: 5px 10px;
border-radius: 999px;
font-size: 12px;
line-height: 1;
border: 1px solid transparent;
}}
.user-chip.fans {{
color: #9a6700;
background: rgba(250, 204, 21, 0.14);
border-color: rgba(234, 179, 8, 0.24);
}}
.user-chip.room {{
color: #1d4ed8;
background: rgba(59, 130, 246, 0.12);
border-color: rgba(59, 130, 246, 0.18);
}}
.user-chip.plain {{
color: #64748b;
background: rgba(148, 163, 184, 0.12);
border-color: rgba(148, 163, 184, 0.16);
}}
.hot-grid {{
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
@@ -500,6 +577,11 @@ def render_daily_report_html(
font-size: 12px;
letter-spacing: .04em;
}}
@media (max-width: 900px) {{
.active-user-grid {{
grid-template-columns: 1fr;
}}
}}
</style>
</head>
<body>
@@ -550,7 +632,9 @@ def render_daily_report_html(
</div>
<div class="aside-card" style="margin-top: 16px;">
<div class="aside-title">核心发言用户</div>
{_render_list(active_user_items, "compact-user-list")}
<div class="active-user-grid">
{_render_active_users(top_active_users)}
</div>
</div>
</div>