Commit 17b0985c authored by fisherdaddy's avatar fisherdaddy

feature: 新增urlencode

parent d47d7d2a
......@@ -8,6 +8,7 @@ import NotFound from './pages/NotFound';
const JsonFormatter = lazy(() => import('./components/JsonFormatter'));
const TextToImage = lazy(() => import('./components/TextToImage'));
const UrlDecode = lazy(() => import('./components/UrlDecode'));
const UrlEncode = lazy(() => import('./components/UrlEncode'));
const About = lazy(() => import('./pages/About'));
const OpenAITimeline = lazy(() => import('./components/OpenAITimeline'));
const PricingCharts = lazy(() => import('./components/PricingCharts'));
......@@ -25,6 +26,7 @@ function App() {
<Route path="/text2image" element={<TextToImage />} />
<Route path="/json-formatter" element={<JsonFormatter />} />
<Route path="/url-decode" element={<UrlDecode />} />
<Route path="/url-encode" element={<UrlEncode />} />
<Route path="/about" element={<About />} />
<Route path="/openai-timeline" element={<OpenAITimeline />} />
<Route path="/llm-model-price" element={<PricingCharts />} />
......
import React, { useState, useCallback } from 'react';
import { Title, Wrapper, Container, InputText, Preview } from '../js/SharedStyles';
import styled from 'styled-components';
import { useTranslation } from '../js/i18n';
import SEO from './SEO';
const EncoderContainer = styled(Container)`
flex-direction: column;
`;
const StyledInputText = styled(InputText)`
height: 100px;
margin-bottom: 20px;
@media (min-width: 768px) {
height: 100px;
width: 100%;
}
`;
const PreviewWrapper = styled.div`
width: 100%;
`;
const Label = styled.label`
font-weight: 500;
font-size: 14px;
color: #5f6368;
margin-bottom: 8px;
display: block;
letter-spacing: 0.1px;
`;
const StyledPreview = styled(Preview)`
background-color: #f8f9fa;
padding: 12px 40px 12px 12px; // 增加右侧 padding 为按钮留出空间
border-radius: 8px;
border: 1px solid #dadce0;
font-size: 14px;
color: #202124;
min-height: 24px; // 确保即使内容为空,也有足够的高度容纳按钮
`;
const ResultContainer = styled.div`
position: relative;
width: 100%;
`;
const CopyButton = styled.button`
position: absolute;
top: 8px;
right: 8px;
background-color: transparent;
border: none;
cursor: pointer;
padding: 4px;
display: flex;
align-items: center;
justify-content: center;
opacity: 0.6;
transition: opacity 0.3s, color 0.3s;
&:hover {
opacity: 1;
}
svg {
width: 16px;
height: 16px;
}
&.copied {
color: #34a853; // 成功复制后的绿色反馈
}
`;
function UrlEncoder() {
const { t } = useTranslation();
const [input, setInput] = useState('');
const [encodedText, setEncodedText] = useState('');
const [isCopied, setIsCopied] = useState(false);
const handleInputChange = (e) => {
const inputValue = e.target.value;
setInput(inputValue);
try {
const encoded = encodeURIComponent(inputValue);
setEncodedText(encoded);
} catch (error) {
setEncodedText('编码出错');
}
};
const handleCopy = useCallback(() => {
navigator.clipboard.writeText(encodedText).then(() => {
setIsCopied(true);
setTimeout(() => setIsCopied(false), 2000);
});
}, [encodedText]);
return (
<>
<SEO
title={t('tools.urlEncode.title')}
description={t('tools.urlEncode.description')}
/>
<Wrapper>
<Title>{t('tools.urlEncode.title')}</Title>
<EncoderContainer>
<StyledInputText
id="urlInput"
placeholder={t('tools.urlEncode.inputLabel')}
value={input}
onChange={handleInputChange}
/>
<PreviewWrapper>
<Label>{t('tools.urlEncode.resultLabel')}</Label>
<ResultContainer>
<StyledPreview>{encodedText}</StyledPreview>
<CopyButton onClick={handleCopy} className={isCopied ? 'copied' : ''}>
{isCopied ? (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>
</svg>
) : (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/>
</svg>
)}
</CopyButton>
</ResultContainer>
</PreviewWrapper>
</EncoderContainer>
</Wrapper>
</>
);
}
export default UrlEncoder;
This diff is collapsed.
This diff is collapsed.
......@@ -5,10 +5,11 @@ import SEO from '../components/SEO';
const tools = [
{ id: 'text2image', icon: 'fa-image', path: '/text2image' },
{ id: 'jsonFormatter', icon: 'fa-code', path: '/json-formatter' },
{ id: 'jsonFormatter', icon: 'fa-jsonformat', path: '/json-formatter' },
{ id: 'urlDecode', icon: 'fa-decode', path: '/url-decode' },
{ id: 'openAITimeline', icon: 'fa-decode', path: '/openai-timeline' },
{ id: 'modelPrice', icon: 'fa-decode', path: '/llm-model-price' },
{ id: 'urlEncode', icon: 'fa-encode', path: '/url-encode' },
{ id: 'openAITimeline', icon: 'fa-openai-timeline', path: '/openai-timeline' },
{ id: 'modelPrice', icon: 'fa-model-price', path: '/llm-model-price' },
];
const Home = () => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment