// ImageBase64Converter.jsx import React, { useState, useCallback } from 'react'; import { Title, Wrapper, Container } from '../js/SharedStyles'; import styled from 'styled-components'; import { useTranslation } from '../js/i18n'; import SEO from '../components/SEO'; const ConverterContainer = styled(Container)` flex-direction: column; gap: 24px; padding: 24px; background: rgba(255, 255, 255, 0.8); backdrop-filter: blur(10px); border: 1px solid rgba(99, 102, 241, 0.1); border-radius: 12px; `; const Section = styled.div` width: 100%; `; const Label = styled.label` font-weight: 500; font-size: 14px; color: #374151; margin-bottom: 12px; display: block; letter-spacing: 0.1px; `; const StyledInputText = styled.textarea` width: 100%; height: 120px; font-size: 15px; padding: 16px; border: 1px solid rgba(99, 102, 241, 0.1); border-radius: 12px; background: rgba(255, 255, 255, 0.8); backdrop-filter: blur(10px); box-sizing: border-box; outline: none; resize: none; transition: all 0.3s ease; line-height: 1.5; &:focus { border-color: rgba(99, 102, 241, 0.3); box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.1); } `; const FileInputWrapper = styled.div` position: relative; width: 100%; height: 120px; border: 2px dashed rgba(99, 102, 241, 0.2); border-radius: 12px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.3s ease; &:hover { border-color: rgba(99, 102, 241, 0.4); background: rgba(99, 102, 241, 0.05); } input { position: absolute; width: 100%; height: 100%; opacity: 0; cursor: pointer; } span { color: #6366F1; font-size: 14px; display: flex; align-items: center; gap: 8px; } `; const ResultContainer = styled.div` position: relative; width: 100%; background: rgba(255, 255, 255, 0.8); backdrop-filter: blur(10px); border-radius: 12px; border: 1px solid rgba(99, 102, 241, 0.1); padding: 16px; min-height: 120px; `; const ActionButton = styled.button` background: rgba(99, 102, 241, 0.1); border: none; border-radius: 6px; padding: 6px 12px; cursor: pointer; display: flex; align-items: center; gap: 6px; font-size: 13px; color: #6366F1; transition: all 0.3s ease; &:hover { background: rgba(99, 102, 241, 0.2); } &.active { background: #6366F1; color: white; } svg { width: 14px; height: 14px; } `; const ImagePreviewContainer = styled.div` position: relative; width: 100%; margin-top: 8px; display: flex; flex-direction: column; gap: 12px; `; const ThumbnailContainer = styled.div` position: relative; width: 120px; height: 120px; border-radius: 8px; overflow: hidden; border: 1px solid rgba(99, 102, 241, 0.1); `; const PreviewActions = styled.div` display: flex; gap: 8px; margin-top: 8px; `; const Thumbnail = styled.img` width: 100%; height: 100%; object-fit: cover; `; const ImageDetails = styled.div` font-size: 13px; color: #6B7280; margin-top: 4px; `; const ErrorText = styled.div` color: #EF4444; font-size: 14px; margin-top: 8px; `; function ImageBase64Converter() { const { t } = useTranslation(); // 图片转 Base64 的状态 const [imageFile, setImageFile] = useState(null); const [base64String, setBase64String] = useState(''); const [isCopied, setIsCopied] = useState(false); // Base64 转图片的状态 const [inputBase64, setInputBase64] = useState(''); const [imageSrc, setImageSrc] = useState(''); const [error, setError] = useState(''); // 处理图片上传 const handleImageUpload = (e) => { const file = e.target.files[0]; if (file) { setImageFile(file); const reader = new FileReader(); reader.onloadend = () => { setBase64String(reader.result); }; reader.readAsDataURL(file); } }; // 复制 Base64 字符串 const handleCopy = useCallback(() => { navigator.clipboard.writeText(base64String).then(() => { setIsCopied(true); setTimeout(() => setIsCopied(false), 2000); }); }, [base64String]); // 处理 Base64 输入变化 const handleBase64InputChange = (e) => { const input = e.target.value.trim(); setInputBase64(input); if (input) { let src = input; if (!input.startsWith('data:image/')) { // 尝试自动推断图片类型 const match = input.match(/^data:(image\/[a-zA-Z]+);base64,/); let mimeType = 'image/png'; // 默认类型 if (match && match[1]) { mimeType = match[1]; } src = `data:${mimeType};base64,${input}`; } setImageSrc(src); setError(''); } else { setImageSrc(''); setError(''); } }; // 图片加载错误处理 const handleImageError = () => { setError(t('tools.imageBase64Converter.invalidBase64')); setImageSrc(''); }; // 下载图片 const handleDownload = () => { const link = document.createElement('a'); link.href = imageSrc; // 尝试从 Base64 字符串中提取文件类型和扩展名 let fileName = 'downloaded_image'; const match = imageSrc.match(/^data:(image\/[a-zA-Z]+);base64,/); if (match && match[1]) { const mime = match[1]; const extension = mime.split('/')[1]; fileName += `.${extension}`; } else { fileName += `.png`; } link.download = fileName; document.body.appendChild(link); link.click(); document.body.removeChild(link); }; return ( <> {t('tools.imageBase64Converter.title')}
{t('tools.imageBase64Converter.dragOrClick')} {base64String && (
{base64String}
{isCopied ? ( ) : ( )} {isCopied ? t('tools.jsonFormatter.copiedMessage') : t('tools.jsonFormatter.copyButton')} {imageFile && ( {t('tools.imageBase64Converter.fileName')}: {imageFile.name}
{t('tools.imageBase64Converter.fileSize')}: {(imageFile.size / 1024).toFixed(2)} KB
)}
)}
{error && {error}} {imageSrc && ( {t('tools.imageBase64Converter.download')} )}
); } export default ImageBase64Converter;