import "./CharsetConverterMobile.css"; import React, { useState, useRef } from "react"; import { Button, Select } from "antd"; import { message } from "@/utils/message"; import { ArrowLeftOutlined, SwapOutlined, CopyOutlined, DeleteOutlined, DownloadOutlined, UploadOutlined, } from "@ant-design/icons"; import { useNavigate } from "react-router-dom"; import ToolFavoriteButton from "@/components/ToolFavoriteButton/ToolFavoriteButton"; import { CHAR_ENCODING_OPTIONS, decodeBytes, encodeText, detectEncoding, fileToBytes, downloadBytes, normalizeEncoding, } from "@/utils/charEncoding"; const ENCODING_OPTIONS = CHAR_ENCODING_OPTIONS.map((opt) => ({ value: opt.value, label: opt.label, })); const sourceOptions = [ { value: "auto", label: "自动检测" }, ...ENCODING_OPTIONS, ]; const CharsetConverterMobile: React.FC = () => { const navigate = useNavigate(); const [inputText, setInputText] = useState(""); const [outputText, setOutputText] = useState(""); const [sourceEncoding, setSourceEncoding] = useState("auto"); const [targetEncoding, setTargetEncoding] = useState("utf-8"); const [fileInfo, setFileInfo] = useState<{ name: string; bytes: Uint8Array } | null>(null); const [convertedBytes, setConvertedBytes] = useState(null); const fileInputRef = useRef(null); const handleFile = async (file: File) => { try { const bytes = await fileToBytes(file); setFileInfo({ name: file.name, bytes }); const detected = detectEncoding(bytes); setInputText(decodeBytes(bytes, detected.encoding)); setSourceEncoding(detected.encoding); setOutputText(""); setConvertedBytes(null); message.success("文件已加载"); } catch (e: any) { message.error(`读取文件失败: ${e.message}`); } }; const handleConvert = () => { if (!fileInfo && !inputText.trim()) { message.warning("请先上传文件或输入文本"); return; } try { let srcBytes: Uint8Array; let src: string; if (fileInfo) { srcBytes = fileInfo.bytes; src = sourceEncoding === "auto" ? detectEncoding(fileInfo.bytes).encoding : sourceEncoding; } else { src = normalizeEncoding(sourceEncoding); srcBytes = encodeText(inputText, src); } const decoded = decodeBytes(srcBytes, src); const outBytes = encodeText(decoded, targetEncoding); setOutputText(decoded); setConvertedBytes(outBytes); message.success("转换成功"); } catch (e: any) { message.error(`转换错误: ${e.message}`); } }; const handleSwap = () => { const tmp = sourceEncoding; setSourceEncoding(targetEncoding); setTargetEncoding(tmp); const tmpText = inputText; setInputText(outputText); setOutputText(tmpText); }; const handleClear = () => { setInputText(""); setOutputText(""); setFileInfo(null); setConvertedBytes(null); setSourceEncoding("auto"); setTargetEncoding("utf-8"); if (fileInputRef.current) { fileInputRef.current.value = ""; } }; const handleCopy = () => { if (!outputText) { message.warning("没有可复制的内容"); return; } navigator.clipboard.writeText(outputText).then(() => { message.success("已复制到剪贴板"); }); }; const handleDownload = () => { if (!convertedBytes || convertedBytes.length === 0) { message.warning("请先进行转换"); return; } const baseName = fileInfo?.name ? fileInfo.name.replace(/\.[^.]+$/, "") : "converted"; const extMatch = fileInfo?.name?.match(/\.[^.]+$/); const ext = extMatch ? extMatch[0] : ".txt"; downloadBytes(convertedBytes, `${baseName}.${targetEncoding}${ext}`, targetEncoding); }; return (
{ const f = e.target.files?.[0]; if (f) handleFile(f); }} />
fileInputRef.current?.click()}> 上传文本文件