video-shuoshan/web/src/components/AnnouncementBanner.tsx
seaislee1209 85f76d8543 feat: v0.8.2~v0.8.4 — 管理后台 UI 修复 + 团队详情重构 + 审计日志系统
v0.8.2: DatePicker/Select 暗色主题、公告跑马灯、Toast 全局化、失败原因 tooltip
v0.8.3: 团队详情抽屉→弹窗重构 + 修改秒数池功能 + member_count 修复
v0.8.4: AdminAuditLog 模型 + 12 处管理操作埋点 + 日志查询页面(/admin/logs)

审计日志覆盖所有管理员 mutation 操作(充值、修改额度、创建/禁用用户等),
记录操作人、变更前后值、IP 地址,支持按操作类型/操作人/日期筛选。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 01:18:44 +08:00

35 lines
1.2 KiB
TypeScript

import { useEffect, useState } from 'react';
import { videoApi } from '../lib/api';
import styles from './AnnouncementBanner.module.css';
export function AnnouncementBanner() {
const [text, setText] = useState('');
const [dismissed, setDismissed] = useState(false);
useEffect(() => {
videoApi.getAnnouncement().then(({ data }) => {
if (data.enabled && data.announcement) {
setText(data.announcement);
}
}).catch(() => {});
}, []);
if (!text || dismissed) return null;
return (
<div className={styles.banner}>
<svg className={styles.icon} width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M22 17H2a3 3 0 0 0 3-3V9a7 7 0 0 1 14 0v5a3 3 0 0 0 3 3zm-8.27 4a2 2 0 0 1-3.46 0" />
</svg>
<div className={styles.marqueeWrapper}>
<span className={styles.marqueeText}>{text}</span>
</div>
<button className={styles.closeBtn} onClick={() => setDismissed(true)} title="关闭">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M18 6L6 18M6 6l12 12" />
</svg>
</button>
</div>
);
}