fix: 导航 i18n 补全 + 模型/提示词页 useT()
- Header 导航 skills/models/articles 改为 t.nav.*(英文正常显示) - 模型百科页全部文字使用 useT()(表格标题、标签等) - 提示词库页标题使用 useT() - models 翻译键补全 contextWindow/maxOutput
This commit is contained in:
@@ -3,45 +3,24 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { API_BASE } from '@/lib/config';
|
||||
import { useT } from '@/i18n';
|
||||
|
||||
interface AiModel {
|
||||
id: number;
|
||||
name: string;
|
||||
provider: string;
|
||||
description: string | null;
|
||||
capabilities: string | null;
|
||||
contextWindow: number | null;
|
||||
maxTokens: number | null;
|
||||
pricing: string | null;
|
||||
isFree: boolean;
|
||||
isFeatured: boolean;
|
||||
icon: string | null;
|
||||
}
|
||||
interface AiModel { id: number; name: string; provider: string; description: string | null; capabilities: string | null; contextWindow: number | null; maxTokens: number | null; pricing: string | null; isFree: boolean; isFeatured: boolean; icon: string | null }
|
||||
|
||||
export default function ModelsPage() {
|
||||
const t = useT();
|
||||
const [models, setModels] = useState<AiModel[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
fetch(`${API_BASE}/models`)
|
||||
.then(r => r.json())
|
||||
.then(setModels)
|
||||
.catch(() => {})
|
||||
.finally(() => setLoading(false));
|
||||
fetch(`${API_BASE}/models`).then(r => r.json()).then(setModels).catch(() => {}).finally(() => setLoading(false));
|
||||
}, []);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||
<div className="text-center mb-12">
|
||||
<Skeleton className="h-9 w-48 mx-auto mb-3" />
|
||||
<Skeleton className="h-5 w-96 mx-auto" />
|
||||
</div>
|
||||
<div className="space-y-3">
|
||||
{[1,2,3,4,5].map(i => (
|
||||
<Skeleton key={i} className="h-16 w-full rounded-xl" />
|
||||
))}
|
||||
</div>
|
||||
<div className="text-center mb-12"><Skeleton className="h-9 w-48 mx-auto mb-3" /><Skeleton className="h-5 w-96 mx-auto" /></div>
|
||||
<div className="space-y-3">{[1,2,3,4,5].map(i => <Skeleton key={i} className="h-16 w-full rounded-xl" />)}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -49,22 +28,20 @@ export default function ModelsPage() {
|
||||
return (
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||
<div className="text-center mb-12">
|
||||
<h1 className="text-3xl font-bold text-foreground">AI 模型百科</h1>
|
||||
<p className="mt-3 text-muted-foreground max-w-2xl mx-auto">
|
||||
收录主流大语言模型,全面对比各项参数,帮助你选择最适合的模型
|
||||
</p>
|
||||
<h1 className="text-3xl font-bold text-foreground">{t.models.title}</h1>
|
||||
<p className="mt-3 text-muted-foreground max-w-2xl mx-auto">{t.models.desc}</p>
|
||||
</div>
|
||||
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-sm">
|
||||
<thead>
|
||||
<tr className="border-b border-border">
|
||||
<th className="text-left py-4 px-4 font-semibold text-foreground">模型名称</th>
|
||||
<th className="text-left py-4 px-4 font-semibold text-foreground">提供商</th>
|
||||
<th className="text-left py-4 px-4 font-semibold text-foreground hidden md:table-cell">能力</th>
|
||||
<th className="text-right py-4 px-4 font-semibold text-foreground hidden lg:table-cell">上下文</th>
|
||||
<th className="text-right py-4 px-4 font-semibold text-foreground hidden lg:table-cell">最大输出</th>
|
||||
<th className="text-center py-4 px-4 font-semibold text-foreground hidden sm:table-cell">价格</th>
|
||||
<th className="text-left py-4 px-4 font-semibold text-foreground">{t.models.tableName}</th>
|
||||
<th className="text-left py-4 px-4 font-semibold text-foreground">{t.models.tableProvider}</th>
|
||||
<th className="text-left py-4 px-4 font-semibold text-foreground hidden md:table-cell">{t.models.tableCapabilities}</th>
|
||||
<th className="text-right py-4 px-4 font-semibold text-foreground hidden lg:table-cell">{t.models.tableContext}</th>
|
||||
<th className="text-right py-4 px-4 font-semibold text-foreground hidden lg:table-cell">{t.models.tableMaxOutput}</th>
|
||||
<th className="text-center py-4 px-4 font-semibold text-foreground hidden sm:table-cell">{t.models.tablePricing}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -72,12 +49,8 @@ export default function ModelsPage() {
|
||||
<tr key={model.id} className="border-b border-border hover:bg-accent/50 transition-colors">
|
||||
<td className="py-4 px-4">
|
||||
<div className="font-semibold text-foreground">{model.name}</div>
|
||||
{model.isFree && (
|
||||
<span className="inline-block mt-1 text-xs px-1.5 py-0.5 bg-green-100 text-green-700 rounded">免费</span>
|
||||
)}
|
||||
{model.isFeatured && !model.isFree && (
|
||||
<span className="inline-block mt-1 text-xs px-1.5 py-0.5 bg-brand-100 text-brand-700 rounded">推荐</span>
|
||||
)}
|
||||
{model.isFree && <span className="inline-block mt-1 text-xs px-1.5 py-0.5 bg-green-100 text-green-700 rounded">{t.models.free}</span>}
|
||||
{model.isFeatured && !model.isFree && <span className="inline-block mt-1 text-xs px-1.5 py-0.5 bg-brand-100 text-brand-700 rounded">{t.models.recommended}</span>}
|
||||
</td>
|
||||
<td className="py-4 px-4 text-muted-foreground">{model.provider}</td>
|
||||
<td className="py-4 px-4 text-muted-foreground hidden md:table-cell max-w-xs">
|
||||
@@ -95,7 +68,7 @@ export default function ModelsPage() {
|
||||
</td>
|
||||
<td className="py-4 px-4 text-center hidden sm:table-cell">
|
||||
<span className={`text-xs px-2 py-1 rounded ${model.isFree ? 'bg-green-100 text-green-700' : 'bg-orange-100 text-orange-700'}`}>
|
||||
{model.isFree ? '免费' : model.pricing?.includes('免费') ? '免费/付费' : '付费'}
|
||||
{model.isFree ? t.models.pricingFree : model.pricing?.includes('免费') ? t.models.pricingMixed : t.models.pricingPaid}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -110,7 +83,7 @@ export default function ModelsPage() {
|
||||
<div key={`card-${model.id}`} className="bg-card rounded-xl border border-border p-6 hover:border-brand-200 transition-colors">
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<h3 className="font-semibold text-foreground">{model.name}</h3>
|
||||
{model.isFree && <span className="text-xs px-1.5 py-0.5 bg-green-100 text-green-700 rounded">免费</span>}
|
||||
{model.isFree && <span className="text-xs px-1.5 py-0.5 bg-green-100 text-green-700 rounded">{t.models.free}</span>}
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground mb-3">{model.provider}</p>
|
||||
<p className="text-sm text-muted-foreground line-clamp-2">{model.description}</p>
|
||||
@@ -120,14 +93,8 @@ export default function ModelsPage() {
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-4 pt-4 border-t border-border grid grid-cols-2 gap-3 text-xs text-muted-foreground">
|
||||
<div>
|
||||
<span className="block text-muted-foreground">上下文</span>
|
||||
{model.contextWindow ? `${(model.contextWindow / 1000).toFixed(0)}K tokens` : '-'}
|
||||
</div>
|
||||
<div>
|
||||
<span className="block text-muted-foreground">最大输出</span>
|
||||
{model.maxTokens ? `${(model.maxTokens / 1024).toFixed(0)}K tokens` : '-'}
|
||||
</div>
|
||||
<div><span className="block text-muted-foreground">{t.models.contextWindow}</span>{model.contextWindow ? `${(model.contextWindow / 1000).toFixed(0)}K tokens` : '-'}</div>
|
||||
<div><span className="block text-muted-foreground">{t.models.maxOutput}</span>{model.maxTokens ? `${(model.maxTokens / 1024).toFixed(0)}K tokens` : '-'}</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user