fix(*): 邮箱与系统公告 - 合并 PR #417 并修复迁移冲突和提醒关闭逻辑
保留历史数据库迁移谱系与公告按需加载,复用邮件配置快照校验注册域名,补充白名单及公告回归测试。
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { AnimatePresence, motion, useReducedMotion } from "motion/react";
|
||||
import { Image as AntImage, Modal } from "antd";
|
||||
import { Button, Image as AntImage, Modal } from "antd";
|
||||
import { Bell, BellOff, CircleAlert, Info, Pin, ShieldAlert, Wrench } from "lucide-react";
|
||||
|
||||
import { aceternityMotion } from "@/lib/aceternity-motion";
|
||||
@@ -11,7 +11,10 @@ type AnnouncementTimelineModalProps = {
|
||||
announcements: SystemAnnouncement[];
|
||||
loading?: boolean;
|
||||
error?: string;
|
||||
automaticPrompt?: boolean;
|
||||
onClose: () => void;
|
||||
onDismissOnce?: () => void;
|
||||
onDismissToday?: () => void;
|
||||
onRetry?: () => void;
|
||||
};
|
||||
|
||||
@@ -22,7 +25,7 @@ const levelMeta: Record<AnnouncementLevel, { label: string; dot: string; icon: t
|
||||
critical: { label: "重要通知", dot: "bg-red-500", icon: ShieldAlert },
|
||||
};
|
||||
|
||||
export function AnnouncementTimelineModal({ open, announcements, loading = false, error = "", onClose, onRetry }: AnnouncementTimelineModalProps) {
|
||||
export function AnnouncementTimelineModal({ open, announcements, loading = false, error = "", automaticPrompt = false, onClose, onDismissOnce, onDismissToday, onRetry }: AnnouncementTimelineModalProps) {
|
||||
const reducedMotion = useReducedMotion();
|
||||
|
||||
return (
|
||||
@@ -30,7 +33,12 @@ export function AnnouncementTimelineModal({ open, announcements, loading = false
|
||||
open={open}
|
||||
width={960}
|
||||
centered
|
||||
footer={null}
|
||||
footer={automaticPrompt ? (
|
||||
<div className="flex flex-wrap justify-end gap-2">
|
||||
<Button onClick={onDismissToday}>今日不再提醒</Button>
|
||||
<Button type="primary" onClick={onDismissOnce}>关闭本次</Button>
|
||||
</div>
|
||||
) : null}
|
||||
onCancel={onClose}
|
||||
title={
|
||||
<div className="flex min-w-0 items-center gap-3 pr-8">
|
||||
@@ -111,7 +119,7 @@ function AnnouncementTimelineItem({ announcement, last, reducedMotion }: { annou
|
||||
{announcement.pinned ? <span className="inline-flex items-center gap-1 text-[var(--fs-label)] font-medium text-amber-500"><Pin className="size-3" />置顶</span> : null}
|
||||
</div>
|
||||
{announcement.imageUrl ? <AntImage src={announcementImageUrl(announcement)} alt={`${announcement.title} 配图`} preview className="mt-3 max-h-36 w-56 max-w-full rounded-lg border border-border/70 bg-muted/20 object-contain p-1" /> : null}
|
||||
<AnnouncementContent content={announcement.content} className="mt-1 text-sm leading-6 text-foreground/75 sm:text-[var(--fs-body-lg)]" />
|
||||
{announcement.content ? <AnnouncementContent content={announcement.content} className="mt-1 text-sm leading-6 text-foreground/75 sm:text-[var(--fs-body-lg)]" /> : null}
|
||||
<time dateTime={announcement.publishedAt} className="mt-2 block text-xs tabular-nums text-foreground/40">{relativeTime(announcement.publishedAt)} · {formatDateTime(announcement.publishedAt)}</time>
|
||||
</div>
|
||||
</motion.article>
|
||||
|
||||
Reference in New Issue
Block a user