"use client"; import { useMemo, useState } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { cn } from "@/lib/utils"; export default function WolaiImportPage() { const router = useRouter(); const searchParams = useSearchParams(); const parentId = useMemo(() => searchParams.get("parentId") ?? "", [searchParams]); const [file, setFile] = useState(null); const [zipPath, setZipPath] = useState(""); const [rootMdPath, setRootMdPath] = useState(""); const [busy, setBusy] = useState(false); const [error, setError] = useState(""); const [warnings, setWarnings] = useState([]); const handleSubmit = async () => { if (!zipPath.trim() && !file) { setError("请填写本地 ZIP 路径,或选择 ZIP 文件"); return; } setBusy(true); setError(""); setWarnings([]); try { const useLocalPath = Boolean(zipPath.trim()); let res: Response; if (useLocalPath) { res = await fetch("/api/wolai-import", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ zipPath: zipPath.trim(), parentId: parentId || undefined, rootMdPath: rootMdPath.trim() || undefined, }), }); } else { if (!file) { setError("请选择 ZIP 文件"); return; } const formData = new FormData(); formData.set("file", file); if (parentId) formData.set("parentId", parentId); if (rootMdPath.trim()) formData.set("rootMdPath", rootMdPath.trim()); res = await fetch("/api/wolai-import", { method: "POST", body: formData }); } const payload = (await res.json().catch(() => null)) as any; if (!res.ok) { const msg = payload?.error ? String(payload.error) : `导入失败:${res.status}`; setError(msg); if (res.status === 409 && Array.isArray(payload?.candidates)) { setWarnings([`无法自动判断入口页面,请在“入口 rootMdPath”填入其中一个:`, ...payload.candidates.map(String)]); } return; } const ws = Array.isArray(payload?.warnings) ? payload.warnings.map(String) : []; setWarnings(ws); const rootDocumentId = String(payload?.rootDocumentId ?? ""); if (rootDocumentId) { router.push(`/documents/${encodeURIComponent(rootDocumentId)}`); return; } setError("导入完成但缺少 rootDocumentId"); } catch (err) { const msg = err instanceof Error ? err.message : "导入失败"; setError(msg); } finally { setBusy(false); } }; return (
导入 Wolai(Markdown ZIP)
本地 ZIP 路径(大文件推荐)
setZipPath(e.target.value)} placeholder="例如:C:\\Users\\liaib\\Downloads\\个人.zip" disabled={busy} />
说明:你的 个人.zip 约 1.26GB,浏览器上传很容易 500。 建议填本地路径并清空 ZIP 文件选择(或不选择文件)。
ZIP 文件
setFile(e.target.files?.[0] ?? null)} disabled={busy} />
说明:请使用 Wolai 导出的“Markdown(含附件/图片)”ZIP。
入口 rootMdPath(可选)
setRootMdPath(e.target.value)} placeholder="例如:dQeAax/个人.md(留空则自动判断)" disabled={busy} />
自动判断失败时会返回候选列表,你可以把其中一个填进来重试。
{parentId ? (
将作为子页面导入到:{parentId}
) : null} {error ?
{error}
: null} {warnings.length > 0 ? (
{warnings.join("\n")}
) : null}
); }