"use client"; import { FormEvent, useMemo, useState } from "react"; import { PrototypeSummary } from "@/lib/prototype"; interface AddPrototypeModalProps { onCreated: (item: PrototypeSummary) => void; } type UploadState = "idle" | "submitting"; export function AddPrototypeModal({ onCreated }: AddPrototypeModalProps) { const [open, setOpen] = useState(false); const [uploadState, setUploadState] = useState("idle"); const [error, setError] = useState(""); const [name, setName] = useState(""); const [description, setDescription] = useState(""); const [file, setFile] = useState(null); const canSubmit = useMemo(() => { return uploadState !== "submitting" && name.trim().length > 0 && Boolean(file); }, [uploadState, name, file]); const reset = () => { setName(""); setDescription(""); setFile(null); setError(""); setUploadState("idle"); }; const close = () => { setOpen(false); reset(); }; const onSubmit = async (event: FormEvent) => { event.preventDefault(); if (!file) { setError("请选择 ZIP 文件"); return; } try { setUploadState("submitting"); setError(""); const formData = new FormData(); formData.append("name", name.trim()); formData.append("description", description.trim()); formData.append("file", file); const response = await fetch("/api/prototypes", { method: "POST", body: formData, }); const payload = await response.json(); if (!response.ok) { throw new Error(payload.error || "上传失败"); } onCreated(payload.data as PrototypeSummary); close(); } catch (submitError) { setError(submitError instanceof Error ? submitError.message : "上传失败"); setUploadState("idle"); } }; return ( <> {open ? (

上传 Axure 原型