// 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')}
{error && {error}}
{imageSrc && (
{t('tools.imageBase64Converter.download')}
)}
>
);
}
export default ImageBase64Converter;