import { useEffect, useMemo, useState } from 'react'; import { Box, Button, Stack, Typography } from '@mui/material'; import { useLazyTranslation } from '@/utils/useLazyTranslation'; import { formatByteSize } from '@/utils/textStatistics'; import { useSnackbar } from '@/components/GlobalSnackbar'; import CopyButton from '@/components/CopyButton'; import TextInputArea from '@/components/TextInputArea'; import { validateJson } from '@/utils/jsonFormatter'; /** 转换结果通用接口 */ export interface ConvertResult { /** 转换后的输出字符串 */ output: string; /** 原始输入的字节大小 */ originalBytes: number; /** 转换后的字节大小 */ outputBytes: number; } /** 转换函数类型 */ export type ConvertFunction = (text: string) => ConvertResult; /** * JSON 转换工具区域组件属性 */ interface JsonConvertSectionProps { /** i18n 命名空间内翻译键的前缀,如 'yamlMode' / 'tomlMode' / 'minifyMode' */ translationPrefix: string; /** 转换函数 */ convertFunction: ConvertFunction; /** 转换按钮的翻译键后缀,默认 'convertButton' */ convertButtonKey?: string; } /** * JSON 转换工具共享组件 * * 适用于 JSON->YAML、JSON->TOML、JSON 压缩等场景, * 提供输入区域、转换按钮和结果展示(含一键复制)。 */ export default function JsonConvertSection({ translationPrefix, convertFunction, convertButtonKey = 'convertButton', }: JsonConvertSectionProps) { const { t } = useLazyTranslation('jsonFormat'); const { showMessage } = useSnackbar(); const [input, setInput] = useState(''); const [error, setError] = useState(null); const [result, setResult] = useState(null); const pk = translationPrefix; // 防抖校验输入 useEffect(() => { const handle = setTimeout(() => { setError(validateJson(input)); }, 300); return () => clearTimeout(handle); }, [input]); const canConvert = useMemo(() => { return input.trim() !== '' && !error; }, [input, error]); const handleConvert = () => { const validationError = validateJson(input); if (validationError) { setError(validationError); setResult(null); return; } try { const convertResult = convertFunction(input); setResult(convertResult); } catch (e) { setError(e instanceof Error ? e.message : String(e)); setResult(null); } }; const handleClear = () => { setInput(''); setError(null); setResult(null); }; return ( {/* 工具栏 */} {/* 输入区 */} { setResult(null); }} /> {/* 转换结果 */} {result && result.output ? ( {/* 结果头部 */} theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.03)' : 'grey.50', }} > {t(`jsonFormat:${pk}OutputLabel`)} {t('jsonFormat:originalSize')}: {formatByteSize(result.originalBytes)} {t('jsonFormat:formattedSize')}: {formatByteSize(result.outputBytes)} {/* 转换内容 */} {result.output} ) : ( theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.03)' : 'grey.50', border: '1px dashed', borderColor: (theme) => theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.15)' : 'grey.300', textAlign: 'center', }} > {t(`jsonFormat:${pk}EmptyHint`)} )} ); }