From bd3e80fd58acd986cd5eea2060cc14f759b7617d Mon Sep 17 00:00:00 2001 From: seaislee1209 Date: Fri, 15 May 2026 16:24:49 +0800 Subject: [PATCH] =?UTF-8?q?feat(notification):=20=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E4=B8=AD=E5=BF=83=E6=94=B9=20accordion=20=E6=A8=A1=E5=BC=8F=20?= =?UTF-8?q?+=20=E8=B7=B3=E8=BD=AC=E6=8C=89=E9=92=AE=20+=20=E5=85=AC?= =?UTF-8?q?=E5=91=8A=E9=A2=9C=E8=89=B2=20CSS=20var=20=E8=87=AA=E9=80=82?= =?UTF-8?q?=E5=BA=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户反馈三点: 1. 公告里"红字"/"蓝字"工具按钮硬编码颜色 #ff4d4f / #00b8e6 在浅色下糊 2. 消息中心列表里公告直接渲染完整 HTML,行被撑得很大 3. 点行就自动 navigate(link_url),用户希望"只看不跳",看完主动决定要不要跳转 改动: a) SettingsPage 公告编辑器颜色按钮(2 个): - 红字: → var(--color-danger) - 蓝字: → var(--color-primary) - 分割线 border-top 颜色 #333 → var(--color-border-card) - 三个都改成 CSS var,自动适配浅/深主题 - title 文案加"(自适应主题)"提示超管 b) NotificationsPage accordion 模式: - 加 expandedId: number | null state,始终最多 1 条展开 - 折叠态:chip + title + 时间 + 一行剥 HTML 后的纯文本预览(stripAndTruncate, 60 字 '…') - 展开态:头部 + 下方完整内容(announcement 用 DOMPurify+HTML / 其他 plain) + link_url 非空时显示【前往查看】按钮(蓝底白字,带箭头 icon) - chevron icon 旋转 0deg/180deg 视觉指示折叠/展开 - 同 id 再点 → 收起;不同 id → 切换(前一个自动收起) - 切页时自动重置 expandedId 为 null c) 点击行为: - handleRowClick(自动跳) → handleToggle(只 markRead + 切 expandedId) - 新加 handleJump(url):用户主动点【前往查看】才触发 navigate / window.open(http url) - 展开区域 onClick 加 stopPropagation 防误触收起 d) smoke test 更新: - 测试公告内容做长用 EXPANDED-ONLY-MARKER 末尾标记,preview 截断后看不到 - 7.2.0 折叠态 preview 截断验证(marker 不可见) - 7.2 展开后 marker 可见 - 7.3 再点收起 marker 不再可见 - 用 chip [公告] 文字作为稳定点击锚点(只在头部出现不在展开内容里) 验证: - typecheck 0 error - announcement-integration-smoke 13/13(从 10 项扩到 13,加 accordion 路径) - v0.20.1-smoke 11/11 + v2-smoke 25/25 + modal-interaction 8/8 全过 - vitest 71 fail / 162 pass 与基线一致 GlobalAnnouncementGate 强弹 modal 行为不变(plan §一 7 — 公告强制阅读语义保留)。 重看路径走 sidebar 大铃铛 → 消息中心 → accordion 展开看全文 → 可点【前往查看】跳。 Co-Authored-By: Claude Opus 4.7 (1M context) --- web/src/pages/NotificationsPage.tsx | 184 +++++++++++++++----- web/src/pages/SettingsPage.tsx | 7 +- web/test/announcement-integration-smoke.mjs | 39 ++++- 3 files changed, 179 insertions(+), 51 deletions(-) diff --git a/web/src/pages/NotificationsPage.tsx b/web/src/pages/NotificationsPage.tsx index fbde682..6cf90ff 100644 --- a/web/src/pages/NotificationsPage.tsx +++ b/web/src/pages/NotificationsPage.tsx @@ -1,10 +1,19 @@ -import { useEffect, type CSSProperties } from 'react'; +import { useEffect, useState, type CSSProperties } from 'react'; import { useNavigate, useSearchParams } from 'react-router-dom'; import DOMPurify from 'dompurify'; import { Sidebar } from '../components/Sidebar'; import { useNotificationStore } from '../store/notification'; import type { AppNotification, NotificationType } from '../types'; +// 剥 HTML 取纯文本前 N 字,用于列表行缩略预览 +function stripAndTruncate(html: string, maxChars = 60): string { + // 用 DOMParser 而非正则,防 `