'use client'; import React, { useState, useEffect } from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faExchangeAlt, faCopy, faCheck, faEraser, faHistory } from '@fortawesome/free-solid-svg-icons'; import ToolHeader from '@/components/ToolHeader'; import BackToTop from '@/components/BackToTop'; import tools from '@/config/tools'; import { useLanguage } from '@/context/LanguageContext'; // 添加CSS变量样式 const styles = { card: "card p-6", container: "min-h-screen flex flex-col max-w-[1440px] mx-auto p-4 md:p-6", textarea: "w-full p-3 bg-block border border-purple-glow rounded-lg text-primary focus:border-purple focus:outline-none focus:ring-1 focus:ring-purple transition-all", label: "text-sm text-secondary font-medium", secondaryText: "text-sm text-tertiary", errorBox: "p-3 bg-red-900/20 border border-red-700/30 rounded-lg text-error", successBox: "p-3 bg-green-900/20 border border-green-700/30 rounded-lg text-success", iconButton: "p-1 text-secondary hover:text-primary disabled:opacity-50 disabled:cursor-not-allowed", directionIndicator: (active: boolean) => active ? "text-primary" : "text-tertiary", historyItem: "flex px-3 py-2 text-sm rounded-lg cursor-pointer text-secondary hover:bg-block-hover transition-colors", noHistoryText: "text-sm text-tertiary py-2 text-center italic", swapButton: "bg-block p-2 rounded-full hover:bg-block-hover transition-colors", encodeLabel: (active: boolean) => `text-sm ${active ? 'text-purple' : 'text-tertiary'} cursor-pointer`, clearButton: "btn-secondary flex items-center gap-2", copyButton: "btn-primary flex items-center gap-2", historyButton: "btn-secondary flex items-center gap-2", } // 类型定义 type Direction = 'encode' | 'decode'; type EncodeMode = 'url' | 'component'; // 历史记录项目接口 interface HistoryItem { id: string; input: string; output: string; direction: Direction; mode: EncodeMode; timestamp: number; } export default function UrlEncoder() { const { t } = useLanguage(); // 从工具配置中获取当前工具信息 const toolConfig = tools.find(tool => tool.code === 'url_encoder'); // 状态管理 const [inputText, setInputText] = useState(''); const [outputText, setOutputText] = useState(''); const [direction, setDirection] = useState('encode'); const [encodeMode, setEncodeMode] = useState('url'); const [error, setError] = useState(''); const [success, setSuccess] = useState(''); const [copied, setCopied] = useState(false); const [history, setHistory] = useState([]); const [showHistory, setShowHistory] = useState(false); // 从localStorage加载历史记录 useEffect(() => { const savedHistory = localStorage.getItem('urlEncoderHistory'); if (savedHistory) { try { setHistory(JSON.parse(savedHistory)); } catch (e) { console.error(t('tools.url_encoder.load_history_error'), e); } } }, [t]); // 保存历史记录到localStorage useEffect(() => { if (history.length > 0) { localStorage.setItem('urlEncoderHistory', JSON.stringify(history)); } }, [history]); // 转换文本 useEffect(() => { if (!inputText.trim()) { setOutputText(''); setError(''); return; } try { let result = ''; if (direction === 'encode') { result = encodeMode === 'url' ? encodeURI(inputText) : encodeURIComponent(inputText); } else { result = encodeMode === 'url' ? decodeURI(inputText) : decodeURIComponent(inputText); } setOutputText(result); setError(''); } catch (err) { if (err instanceof Error) { setError(err.message); } else { setError(t('tools.url_encoder.error_processing')); } setOutputText(''); } }, [inputText, direction, encodeMode, t]); // 反转转换方向 const swapDirection = () => { setDirection(prev => prev === 'encode' ? 'decode' : 'encode'); setInputText(outputText); setOutputText(''); setError(''); }; // 复制输出结果 const copyOutput = () => { if (!outputText) return; navigator.clipboard.writeText(outputText) .then(() => { setCopied(true); setSuccess(t('tools.url_encoder.copied_to_clipboard')); // 添加到历史记录 if (inputText.trim() && outputText.trim()) { const newItem: HistoryItem = { id: Date.now().toString(), input: inputText, output: outputText, direction, mode: encodeMode, timestamp: Date.now() }; setHistory(prev => [newItem, ...prev.slice(0, 9)]); // 保留最近10条记录 } setTimeout(() => { setCopied(false); setSuccess(''); }, 2000); }) .catch(err => { console.error(t('tools.url_encoder.copy_failed'), err); setError(t('tools.url_encoder.copy_failed')); }); }; // 清空输入输出 const clearAll = () => { setInputText(''); setOutputText(''); setError(''); setSuccess(''); }; // 从历史记录中恢复 const restoreFromHistory = (item: HistoryItem) => { setInputText(item.input); setDirection(item.direction); setEncodeMode(item.mode); setShowHistory(false); }; // 清空历史记录 const clearHistory = () => { setHistory([]); localStorage.removeItem('urlEncoderHistory'); }; // 格式化时间 const formatTime = (timestamp: number) => { const date = new Date(timestamp); return date.toLocaleString(); }; return (
{/* 工具头部 */} {/* 主内容区 */}
{/* 左侧面板 - 输入区域 */}
{/* 转换选项 */}
{/* 转换方向选择器 */}
{t('tools.url_encoder.original_text')} {t('tools.url_encoder.url_encoded_text')}
{/* 编码模式选择器 */}

{encodeMode === 'url' ? t('tools.url_encoder.uri_encoding_description') : t('tools.url_encoder.uri_component_description')}

{/* 输入文本区域 */}