import { useState, useEffect } from "react"; import { api } from "../api/client"; import styles from "./PreviewPanel.module.css"; interface Props { creativeId: string; creativeStatus: string; theme: Record; } export default function PreviewPanel({ creativeId, creativeStatus, theme }: Props) { const [previewUrl, setPreviewUrl] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(""); const [loaded, setLoaded] = useState(false); const canPreview = creativeStatus === "assets_ready" || creativeStatus === "built" || creativeStatus === "building"; // 预览启动后 5s 超时 useEffect(() => { if (!previewUrl || loaded) return; const timer = setTimeout(() => { if (!loaded) setError("预览加载超时,请检查控制台或重试"); }, 10000); return () => clearTimeout(timer); }, [previewUrl, loaded]); // 退出页面时停止预览 useEffect(() => { return () => { if (previewUrl) { api.stopPreview(creativeId).catch(() => {}); } }; }, []); // eslint-disable-line react-hooks/exhaustive-deps async function handleStart() { setLoading(true); setError(""); setLoaded(false); try { const res = await api.startPreview(creativeId, theme); setPreviewUrl(res.data.url); } catch (err: any) { setError(err.message); } finally { setLoading(false); } } async function handleStop() { try { await api.stopPreview(creativeId); } catch {} setPreviewUrl(null); setLoaded(false); setError(""); } return (

实时预览

{!previewUrl ? ( ) : ( )}
{!canPreview && !previewUrl && (

上传素材后即可预览

)} {error &&

{error}

} {loading && (
Vite 开发服务器启动中,请稍候…
)} {previewUrl && (