diff --git a/src/pages/Jwt/JwtSection.tsx b/src/pages/Jwt/JwtSection.tsx deleted file mode 100644 index 8d78ecd..0000000 --- a/src/pages/Jwt/JwtSection.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { CopyButton } from '@/components/CopyButton'; -import { stringifyJson } from '@/utils/jwt'; -import { cn } from '@/lib/utils'; - -interface JwtSectionProps { - title: string; - content: unknown; - colorClass: string; - bgClass: string; - borderClass: string; -} - -export default function JwtSection({ - title, - content, - colorClass, - bgClass, - borderClass, -}: JwtSectionProps) { - return ( -
-
- - {title} - - -
-
-        {content ? stringifyJson(content) : '无法解析'}
-      
-
- ); -} diff --git a/src/pages/Jwt/components/JwtCopyBlock.tsx b/src/pages/Jwt/components/JwtCopyBlock.tsx new file mode 100644 index 0000000..4f865e8 --- /dev/null +++ b/src/pages/Jwt/components/JwtCopyBlock.tsx @@ -0,0 +1,30 @@ +import { CopyButton } from '@/components/CopyButton'; +import { cn } from '@/lib/utils'; + +interface JwtCopyBlockProps { + title: string; + copyText: string; + titleClassName?: string; + containerClassName?: string; + children: React.ReactNode; +} + +export default function JwtCopyBlock({ + title, + copyText, + titleClassName, + containerClassName, + children, +}: JwtCopyBlockProps) { + return ( +
+
+ + {title} + + +
+ {children} +
+ ); +} diff --git a/src/pages/Jwt/components/JwtResultView.tsx b/src/pages/Jwt/components/JwtResultView.tsx new file mode 100644 index 0000000..b3464bf --- /dev/null +++ b/src/pages/Jwt/components/JwtResultView.tsx @@ -0,0 +1,49 @@ +import { stringifyJson } from '@/utils/jwt'; +import type { JwtResult } from '@/utils/jwt'; +import { cn } from '@/lib/utils'; +import { + JWT_JSON_CONTENT_CLASS, + JWT_SECTION_CONFIG, + JWT_SIGNATURE_SECTION, + JWT_TEXT_CONTENT_CLASS, +} from '../constants'; +import JwtCopyBlock from './JwtCopyBlock'; + +interface JwtResultViewProps { + result: JwtResult; +} + +export default function JwtResultView({ result }: JwtResultViewProps) { + return ( +
+ {JWT_SECTION_CONFIG.map(({ contentKey, title, colorClass, bgClass, borderClass }) => { + const content = result[contentKey]; + + return ( + +
+              {content ? stringifyJson(content) : '无法解析'}
+            
+
+ ); + })} + + + + {result.signature || JWT_SIGNATURE_SECTION.emptyLabel} + + +
+ ); +} diff --git a/src/pages/Jwt/constants.ts b/src/pages/Jwt/constants.ts new file mode 100644 index 0000000..64aacc8 --- /dev/null +++ b/src/pages/Jwt/constants.ts @@ -0,0 +1,41 @@ +export const JWT_INPUT_PLACEHOLDER = '在此粘贴 JWT 令牌 (Encoded JWT)...'; + +export type JwtSectionContentKey = 'header' | 'payload'; + +export interface JwtSectionConfig { + contentKey: JwtSectionContentKey; + title: string; + colorClass: string; + borderClass: string; + bgClass: string; +} + +export const JWT_SECTION_CONFIG: JwtSectionConfig[] = [ + { + contentKey: 'header', + title: 'HEADER: 算法 & 令牌类型', + colorClass: 'text-[#fb015b] dark:text-rose-400', + borderClass: 'border-[#fb015b]/20 dark:border-rose-500/20', + bgClass: 'bg-[#fb015b]/5 dark:bg-rose-500/5', + }, + { + contentKey: 'payload', + title: 'PAYLOAD: 数据', + colorClass: 'text-[#a03aff] dark:text-purple-400', + borderClass: 'border-[#a03aff]/20 dark:border-purple-500/20', + bgClass: 'bg-[#a03aff]/5 dark:bg-purple-500/5', + }, +]; + +export const JWT_SIGNATURE_SECTION = { + title: '签名', + titleClassName: 'text-muted-foreground/90', + containerClassName: 'border border-border bg-secondary/40', + emptyLabel: '无签名', +} as const; + +export const JWT_JSON_CONTENT_CLASS = + 'm-0 p-3 bg-muted/30 dark:bg-muted/10 rounded-lg text-xs font-mono overflow-x-auto whitespace-pre-wrap break-all border border-border/50 text-foreground/90 leading-relaxed select-text'; + +export const JWT_TEXT_CONTENT_CLASS = + 'block text-xs font-mono break-all text-foreground/80 bg-muted/30 dark:bg-muted/10 p-3 rounded-lg border border-border/50 leading-relaxed select-text'; diff --git a/src/pages/Jwt/index.tsx b/src/pages/Jwt/index.tsx index ee75e12..3754441 100644 --- a/src/pages/Jwt/index.tsx +++ b/src/pages/Jwt/index.tsx @@ -1,66 +1,26 @@ import TextInputArea from '@/components/TextInputArea'; -import { CopyButton } from '@/components/CopyButton'; -import EmptyPlaceholder from '@/components/EmptyPlaceholder'; -import JwtSection from './JwtSection'; +import JwtResultView from './components/JwtResultView'; +import { JWT_INPUT_PLACEHOLDER } from './constants'; import { useJwt } from './useJwt'; export default function Index() { const { jwtInput, result, handleChange, handleClear } = useJwt(); return ( -
-
- +
+ - {result && !result.error && ( -
- - - - -
-
- - {'签名'} - - -
- - {result.signature || '无签名'} - -
-
- )} - - {result?.error && ( - {'无效的 JSON 格式'} - )} -
+ {result && !result.error && }
); }