前端重构实现

This commit is contained in:
2025-12-22 16:38:06 +08:00
parent cd6d995d5a
commit 26574e3db7
54 changed files with 8976 additions and 0 deletions
+87
View File
@@ -0,0 +1,87 @@
import * as Dialog from '@radix-ui/react-dialog';
import { X } from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
/**
* Modal 组件
* 使用 Radix UI Dialog 实现的模态弹窗
* @param {Object} props
* @param {boolean} props.isOpen - 是否打开
* @param {Function} props.onClose - 关闭回调
* @param {React.ReactNode} props.children - 子元素
* @param {'sm'|'md'|'lg'} props.maxWidth - 最大宽度
* @param {string} props.title - 标题(可选)
*/
const Modal = ({
isOpen,
onClose,
children,
maxWidth = 'md',
title
}) => {
// 最大宽度映射
const maxWidthMap = {
sm: 'max-w-sm',
md: 'max-w-lg',
lg: 'max-w-2xl'
};
return (
<Dialog.Root open={isOpen} onOpenChange={(open) => !open && onClose()}>
<AnimatePresence>
{isOpen && (
<Dialog.Portal forceMount>
{/* 遮罩层 */}
<Dialog.Overlay asChild>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 bg-black/60 backdrop-blur-xl z-[100]"
/>
</Dialog.Overlay>
{/* 内容区 */}
<Dialog.Content asChild>
<motion.div
initial={{ opacity: 0, scale: 0.95, y: 20 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.95, y: 20 }}
transition={{ duration: 0.3, ease: [0.16, 1, 0.3, 1] }}
className={`
fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2
glass-card ${maxWidthMap[maxWidth]} w-[calc(100%-2rem)] p-8
border border-white/10 shadow-2xl z-[101]
`}
>
{/* 关闭按钮 */}
<Dialog.Close asChild>
<button
className="absolute top-6 right-6 text-white/40 hover:text-white transition-colors"
aria-label="关闭"
>
<X className="w-5 h-5" />
</button>
</Dialog.Close>
{/* 标题 */}
{title && (
<Dialog.Title className="text-2xl font-serif mb-6">
{title}
</Dialog.Title>
)}
{/* 内容 */}
<div className="max-h-[70vh] overflow-y-auto pr-2 custom-scrollbar">
{children}
</div>
</motion.div>
</Dialog.Content>
</Dialog.Portal>
)}
</AnimatePresence>
</Dialog.Root>
);
};
export default Modal;