video-shuoshan/web/src/components/AnnouncementModal.tsx
seaislee1209 f4255a04ee
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 10m8s
fix: 公告弹窗改为 CSS Module 规范
inline style 改为 CSS Module,z-index/圆角/关闭按钮与其他弹窗统一

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 22:13:42 +08:00

59 lines
1.9 KiB
TypeScript

import { useEffect, useState, useCallback } from 'react';
import { videoApi } from '../lib/api';
import styles from './AnnouncementModal.module.css';
interface Props {
/** If true, force show even if already read (for manual open) */
forceOpen?: boolean;
onClose?: () => void;
}
export function AnnouncementModal({ forceOpen, onClose }: Props) {
const [content, setContent] = useState('');
const [visible, setVisible] = useState(false);
useEffect(() => {
videoApi.getAnnouncement().then(({ data }) => {
if (data.enabled && data.announcement) {
setContent(data.announcement);
if (forceOpen || !data.is_read) {
setVisible(true);
}
}
}).catch(() => {});
}, [forceOpen]);
const handleClose = useCallback(() => {
videoApi.readAnnouncement().catch(() => {});
setVisible(false);
onClose?.();
}, [onClose]);
if (!visible || !content) return null;
return (
<div className={styles.overlay} onMouseDown={(e) => { if (e.target === e.currentTarget) handleClose(); }}>
<div className={styles.modal}>
<div className={styles.header}>
<span className={styles.title}></span>
<button className={styles.closeBtn} onClick={handleClose}>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" />
</svg>
</button>
</div>
<div
className={styles.content}
dangerouslySetInnerHTML={{ __html: `<style>li{margin-left:16px}</style>${content}` }}
/>
<div className={styles.footer}>
<button className={styles.confirmBtn} onClick={handleClose}>
</button>
</div>
</div>
</div>
);
}