import { motion, AnimatePresence } from 'framer-motion' import { createPortal } from 'react-dom' import { X, History, CalendarDays, Tag } from 'lucide-react' import { changelogEntries } from '@/data' import type { ChangelogType } from '@/types/itto' interface ChangelogModalProps { isOpen: boolean onClose: () => void } const containerVariants = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { staggerChildren: 0.06, }, }, } const itemVariants = { hidden: { opacity: 0, y: 12 }, visible: { opacity: 1, y: 0, transition: { duration: 0.25, }, }, } const typeMeta: Record = { feat: { label: '新功能', className: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-300' }, fix: { label: '修复', className: 'bg-rose-100 text-rose-700 dark:bg-rose-900/30 dark:text-rose-300' }, style: { label: '样式', className: 'bg-pink-100 text-pink-700 dark:bg-pink-900/30 dark:text-pink-300' }, refactor: { label: '重构', className: 'bg-violet-100 text-violet-700 dark:bg-violet-900/30 dark:text-violet-300' }, docs: { label: '文档', className: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300' }, perf: { label: '性能', className: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300' }, test: { label: '测试', className: 'bg-cyan-100 text-cyan-700 dark:bg-cyan-900/30 dark:text-cyan-300' }, chore: { label: '工程', className: 'bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300' }, } function formatDate(date: string) { const [year, month, day] = date.split('-').map(Number) if (!year || !month || !day) return date return `${year}年${month}月${day}日` } // 按日期分组 function groupByDate(entries: typeof changelogEntries) { const groups = new Map() entries.forEach((entry) => { const existing = groups.get(entry.date) || [] groups.set(entry.date, [...existing, entry]) }) return Array.from(groups.entries()).sort((a, b) => b[0].localeCompare(a[0])) } export function ChangelogModal({ isOpen, onClose }: ChangelogModalProps) { const groupedEntries = groupByDate(changelogEntries) // 使用 Portal 将模态框渲染到 body,避免被 Header 的层叠上下文限制 if (typeof document === 'undefined') return null return createPortal( {isOpen && ( <> {/* 背景遮罩 */} {/* 模态框 */}
{/* 头部 */}

更新日志

共 {changelogEntries.length} 条记录

{/* 内容区域 */}
{changelogEntries.length > 0 ? ( {/* 按日期分组显示 */} {groupedEntries.map(([date, entries]) => (
{/* 日期标题 */}

{formatDate(date)}

{/* 该日期下的更新列表 - 统一卡片 */} {entries.map((entry, index) => { const meta = typeMeta[entry.type] return (
{/* 标签 */}
{meta.label} {entry.scope && ( {entry.scope} )}
{/* 标题 */}

{entry.title}

) })}
))} ) : (

暂无更新记录

)}
)} , document.body ) }