修复多个问题

This commit is contained in:
ZhangYonghao
2026-03-21 20:32:19 +08:00
parent f2c371b87d
commit 10d463a55f
12 changed files with 1021 additions and 275 deletions

View File

@@ -1,88 +1,214 @@
import { useState } from 'react';
"use client";
import { FormEvent, useState } from "react";
type GenerateResponse = {
message: string;
unique_id: string;
url: string;
query_url: string;
title?: string | null;
source?: string | null;
request_id?: string | null;
size_bytes: number;
created_at: string;
expires_at: string;
};
const apiBaseUrl =
process.env.NEXT_PUBLIC_API_BASE_URL?.replace(/\/$/, "") ||
"http://localhost:8000";
const initialHtml = `<section>
<h1>勾股定理</h1>
<p>在直角三角形中,两条直角边长度分别为 a、b斜边长度为 c则 a² + b² = c²。</p>
<ul>
<li>适用对象:直角三角形</li>
<li>核心关系:两直角边平方和等于斜边平方</li>
<li>常见用途:求边长、验证三角形是否为直角三角形</li>
</ul>
</section>`;
export default function Home() {
const [htmlContent, setHtmlContent] = useState('');
const [title, setTitle] = useState("知识点讲解");
const [source, setSource] = useState("tencent-agent");
const [requestId, setRequestId] = useState("");
const [htmlContent, setHtmlContent] = useState(initialHtml);
const [loading, setLoading] = useState(false);
const [result, setResult] = useState<{ url: string } | null>(null);
const [result, setResult] = useState<GenerateResponse | null>(null);
const [error, setError] = useState<string | null>(null);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
setLoading(true);
setError(null);
setResult(null);
try {
const response = await fetch('http://localhost:8000/api/html/generate', {
method: 'POST',
const response = await fetch(`${apiBaseUrl}/api/html/generate`, {
method: "POST",
headers: {
'Content-Type': 'application/json',
"Content-Type": "application/json",
},
body: JSON.stringify({ html_content: htmlContent }),
body: JSON.stringify({
title,
source,
request_id: requestId || undefined,
html_content: htmlContent,
}),
});
const data = await response.json();
if (!response.ok) {
throw new Error('生成 HTML 文件失败');
throw new Error(data.detail || data.message || "生成 HTML 失败");
}
const data = await response.json();
setResult({ url: data.url });
} catch (err) {
setError('生成 HTML 文件失败,请稍后重试');
console.error(err);
setResult(data);
} catch (submissionError) {
setError(
submissionError instanceof Error
? submissionError.message
: "生成 HTML 失败,请稍后重试。"
);
} finally {
setLoading(false);
}
};
return (
<div className="max-w-4xl mx-auto">
<h2 className="text-2xl font-bold mb-6">HTML </h2>
<form onSubmit={handleSubmit} className="space-y-6">
<div>
<label htmlFor="html-content" className="block text-sm font-medium mb-2">
HTML
</label>
<textarea
id="html-content"
value={htmlContent}
onChange={(e) => setHtmlContent(e.target.value)}
rows={10}
className="w-full p-4 border border-border rounded-md bg-card focus:outline-none focus:ring-2 focus:ring-primary"
placeholder="请输入 HTML 内容..."
/>
<div className="mx-auto max-w-5xl space-y-8">
<section className="rounded-3xl border border-border bg-card p-8 shadow-sm">
<div className="max-w-3xl space-y-3">
<p className="text-sm uppercase tracking-[0.3em] text-muted-foreground">
HTML Explanation API
</p>
<h2 className="text-3xl font-bold text-foreground">
HTML
</h2>
<p className="text-muted-foreground">
HTML
</p>
</div>
<div>
</section>
<form
onSubmit={handleSubmit}
className="space-y-6 rounded-3xl border border-border bg-card p-8 shadow-sm"
>
<div className="grid gap-4 md:grid-cols-2">
<label className="space-y-2">
<span className="text-sm font-medium">title</span>
<input
value={title}
onChange={(event) => setTitle(event.target.value)}
className="w-full rounded-2xl border border-border bg-background px-4 py-3 outline-none ring-0 transition focus:border-primary"
placeholder="页面标题"
/>
</label>
<label className="space-y-2">
<span className="text-sm font-medium">source</span>
<input
value={source}
onChange={(event) => setSource(event.target.value)}
className="w-full rounded-2xl border border-border bg-background px-4 py-3 outline-none ring-0 transition focus:border-primary"
placeholder="来源,例如 tencent-agent"
/>
</label>
</div>
<label className="block space-y-2">
<span className="text-sm font-medium">request_id</span>
<input
value={requestId}
onChange={(event) => setRequestId(event.target.value)}
className="w-full rounded-2xl border border-border bg-background px-4 py-3 outline-none ring-0 transition focus:border-primary"
placeholder="可选的请求追踪 ID"
/>
</label>
<label className="block space-y-2">
<span className="text-sm font-medium">html_content</span>
<textarea
value={htmlContent}
onChange={(event) => setHtmlContent(event.target.value)}
rows={18}
className="w-full rounded-3xl border border-border bg-background px-4 py-4 font-mono text-sm outline-none ring-0 transition focus:border-primary"
placeholder="请输入完整 HTML 或 HTML 片段"
/>
</label>
<div className="flex flex-wrap items-center gap-4">
<button
type="submit"
disabled={loading || !htmlContent.trim()}
className="bg-primary text-primary-foreground px-6 py-2 rounded-md hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
className="rounded-full bg-primary px-6 py-3 text-sm font-semibold text-primary-foreground transition hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50"
>
{loading ? '生成中...' : '生成 HTML 文件'}
{loading ? "生成中..." : "生成 HTML 链接"}
</button>
<p className="text-sm text-muted-foreground">
{apiBaseUrl}/api/html/generate
</p>
</div>
</form>
{error && (
<div className="mt-6 p-4 bg-destructive/10 text-destructive rounded-md">
{error ? (
<section className="rounded-3xl border border-destructive/20 bg-destructive/10 p-6 text-destructive">
{error}
</div>
)}
</section>
) : null}
{result && (
<div className="mt-6 p-4 bg-accent/10 text-accent rounded-md">
<h3 className="font-medium mb-2"></h3>
<p className="mb-2"> HTML 访</p>
<a
href={result.url}
target="_blank"
rel="noopener noreferrer"
className="text-primary hover:underline"
>
{result.url}
</a>
</div>
)}
{result ? (
<section className="space-y-4 rounded-3xl border border-border bg-card p-8 shadow-sm">
<div>
<h3 className="text-xl font-semibold"></h3>
<p className="text-sm text-muted-foreground">{result.message}</p>
</div>
<div className="grid gap-4 md:grid-cols-2">
<div className="rounded-2xl bg-background p-4">
<p className="text-xs uppercase tracking-[0.2em] text-muted-foreground">
unique_id
</p>
<p className="mt-2 break-all font-mono text-sm">{result.unique_id}</p>
</div>
<div className="rounded-2xl bg-background p-4">
<p className="text-xs uppercase tracking-[0.2em] text-muted-foreground">
size_bytes
</p>
<p className="mt-2 font-mono text-sm">{result.size_bytes}</p>
</div>
</div>
<div className="space-y-3 rounded-2xl bg-background p-4">
<p className="text-xs uppercase tracking-[0.2em] text-muted-foreground">
url
</p>
<a
href={result.url}
target="_blank"
rel="noreferrer"
className="break-all text-sm text-primary underline-offset-4 hover:underline"
>
{result.url}
</a>
</div>
<div className="space-y-3 rounded-2xl bg-background p-4">
<p className="text-xs uppercase tracking-[0.2em] text-muted-foreground">
query_url
</p>
<a
href={result.query_url}
target="_blank"
rel="noreferrer"
className="break-all text-sm text-primary underline-offset-4 hover:underline"
>
{result.query_url}
</a>
</div>
<p className="text-sm text-muted-foreground">
{new Date(result.created_at).toLocaleString("zh-CN")}
{new Date(result.expires_at).toLocaleString("zh-CN")}
</p>
</section>
) : null}
</div>
);
}
}