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>
35 lines
1.2 KiB
TypeScript
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>
|
|
);
|
|
}
|