"use client"; import { useState } from "react"; import { ForwardEmail } from "@prisma/client"; import { File, FileArchive, FileAudio, FileImage, FileSpreadsheet, FileText, FileVideo, } from "lucide-react"; import { useTranslations } from "next-intl"; import { siteConfig } from "@/config/site"; import { cn, downloadFile, formatDate, formatFileSize } from "@/lib/utils"; import { Icons } from "@/components/shared/icons"; import { BlurImg } from "../shared/blur-image"; import { Button } from "../ui/button"; import { Modal } from "../ui/modal"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "../ui/tooltip"; import EmailViewer from "./EmailViewer"; interface EmailDetailProps { email: ForwardEmail | undefined; selectedEmailId: string | null; onClose: () => void; onMarkAsRead: () => void; } interface Attachment { filename: string; r2Path: string; mimeType: string; size: number; } const fileTypeMap: { [key: string]: string } = { "application/pdf": "pdf", "image/jpeg": "jpeg", "image/png": "png", "image/gif": "gif", "application/msword": "doc", "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx", "application/vnd.ms-excel": "xls", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx", "application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx", "audio/mpeg": "mp3", "video/mp4": "mp4", "application/zip": "zip", default: "unknown", }; const fileTypeIcons: { [key: string]: React.ComponentType } = { "application/pdf": FileText, // PDF 文件 "image/jpeg": FileImage, // JPEG 图片 "image/png": FileImage, // PNG 图片 "image/gif": FileImage, // GIF 图片 "application/msword": FileText, // Word 文档 (.doc) "application/vnd.openxmlformats-officedocument.wordprocessingml.document": FileText, // Word 文档 (.docx) "application/vnd.ms-excel": FileSpreadsheet, // Excel 表格 (.xls) "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": FileSpreadsheet, // Excel 表格 (.xlsx) "application/vnd.openxmlformats-officedocument.presentationml.presentation": FileSpreadsheet, // PowerPoint 文档 "audio/mpeg": FileAudio, // MP3 音频 "video/mp4": FileVideo, // MP4 视频 "application/zip": FileArchive, // ZIP 压缩文件 default: File, // 默认图标 }; export default function EmailDetail({ email, selectedEmailId, onClose, onMarkAsRead, }: EmailDetailProps) { const [previewImage, setPreviewImage] = useState(null); const t = useTranslations("Email"); function getFileIcon(type: string): React.ComponentType { const icon = Object.keys(fileTypeIcons).find((key) => type.toLowerCase().startsWith(key), ); return fileTypeIcons[icon || "default"]; } const handleDownload = async (attachment: Attachment) => { downloadFile( `${siteConfig.emailR2Domain}/${attachment.r2Path}`, attachment.filename, ); // downloadFileFromUrl( // `${siteConfig.emailR2Domain}/${attachment.r2Path}`, // attachment.filename, // ); }; if (!email) return null; let attachments: Attachment[] = []; try { if (email.attachments) { attachments = JSON.parse(email.attachments); } } catch (error) { console.log("Failed to parse attachments:", error); } // 处理邮件内容中的图片链接 const processContent = (content: string): string => { if (!content || attachments.length === 0) return content; let processedContent = content; // 如果是 HTML,解析 DOM 并替换 标签的 src if (email.html) { const parser = new DOMParser(); const doc = parser.parseFromString(content, "text/html"); const images = Array.from(doc.getElementsByTagName("img")); // 转换为数组 images.forEach((img) => { const alt = img.getAttribute("alt") || ""; const matchingAttachment = attachments.find( (att) => att.filename === alt, ); if (matchingAttachment) { img.setAttribute( "src", `${siteConfig.emailR2Domain}/${matchingAttachment.r2Path}`, ); } }); processedContent = doc.documentElement.outerHTML; // 返回完整的 HTML } else if (email.text) { // 如果是纯文本,替换文件名 attachments.forEach((attachment) => { const regex = new RegExp(`\\b${attachment.filename}\\b`, "g"); processedContent = processedContent.replace( regex, `${siteConfig.emailR2Domain}/${attachment.r2Path}`, ); }); } return processedContent; }; return (
{email.subject?.[0].toUpperCase() || email.fromName?.[0].toUpperCase() || "U"}

{email.subject}

{t("From")}: {email.fromName} <{email.from} > {email.fromName}
{email.from}

{t("To")}: {email.to}

{email.replyTo && email.replyTo !== '""' && (

{t("Reply-To")}: {email.replyTo}

)}

{t("Date")}: {formatDate(email.date as any)}

{attachments.length > 0 && (

{t("Attachments")}: {attachments.length}

)}
{/*
*/} {attachments.length > 0 && (

{t("Attachments")} ({attachments.length})

{attachments.map((attachment, index) => { const FileIcon = getFileIcon(attachment.mimeType); // 动态获取图标 return (
{attachment.mimeType.startsWith("image/") ? ( setPreviewImage( `${siteConfig.emailR2Domain}/${attachment.r2Path}`, ) } /> ) : ( )}

{attachment.filename}

{fileTypeMap[attachment.mimeType] || attachment.mimeType}{" "} • {formatFileSize(attachment.size)}

); })}
)}
{/* 图片预览 Modal */} {previewImage && ( setPreviewImage(null)} >
Preview
)}
); }