php做电商网站的难点,有专门做ppt的网站有哪些,谷歌搜索入口中文,王野天天通义万相图像生成模型支持图像编辑、图文混排输出#xff0c;满足多样化生成与集成需求。
以下是一个基于 React 的通义万相 (Wan) API 可视化调用面板。
效果图#xff1a;
由于目前通义万相#xff08;Wan 2.1/2.0#xff09;的视频生成通常是异步任务#xff08;提…通义万相图像生成模型支持图像编辑、图文混排输出满足多样化生成与集成需求。以下是一个基于 React 的通义万相 (Wan) API 可视化调用面板。效果图由于目前通义万相Wan 2.1/2.0的视频生成通常是异步任务提交任务 - 轮询状态 - 获取结果这个面板完整实现了这套全流程逻辑。核心功能配置管理输入 API Key存储在本地浏览器内存中刷新即焚保证安全。参数控制支持模型选择预置了 Wan 2.1 等、提示词、分辨率、时长等参数调节。任务流处理自动处理“提交任务”与“轮询进度”的交互逻辑。调试友好右侧实时显示发送的 JSON 请求体和 API 返回的原始日志方便排查问题。id: wan-api-dashboard name: Tongyi Wan API Dashboard type: tsx content: |- import React, { useState, useEffect, useRef } from react; import { Play, Image as ImageIcon, Settings, Terminal, Loader2, AlertCircle, CheckCircle2, Copy, Eye, EyeOff } from lucide-react; import { Alert, AlertDescription, AlertTitle } from /components/ui/alert; import { Tabs, TabsContent, TabsList, TabsTrigger } from /components/ui/tabs; import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from /components/ui/card; import { Button } from /components/ui/button; import { Input } from /components/ui/input; import { Label } from /components/ui/label; import { Textarea } from /components/ui/textarea; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from /components/ui/select; import { Switch } from /components/ui/switch; import { ScrollArea } from /components/ui/scroll-area; import { Badge } from /components/ui/badge; const WanDashboard () { // Configuration State const [apiKey, setApiKey] useState(); const [showKey, setShowKey] useState(false); // Generation State const [prompt, setPrompt] useState(A cinematic shot of a futuristic city with flying cars, cyberpunk style, neon lights, 4k resolution); const [negativePrompt, setNegativePrompt] useState(low quality, blurry, distorted); const [model, setModel] useState(wan2.1-t2v-plus); const [resolution, setResolution] useState(1280*720); const [duration, setDuration] useState(5); // Process State const [status, setStatus] useState(idle); // idle, submitting, polling, success, error const [taskId, setTaskId] useState(); const [progress, setProgress] useState(0); const [resultUrl, setResultUrl] useState(); const [logs, setLogs] useState([]); const [errorMsg, setErrorMsg] useState(); // Refs for polling const pollInterval useRef(null); const addLog (type, message, data null) { const timestamp new Date().toLocaleTimeString(); setLogs(prev [{ time: timestamp, type, message, data }, ...prev]); }; // Cleanup on unmount useEffect(() { return () { if (pollInterval.current) clearInterval(pollInterval.current); }; }, []); const handleGenerate async () { if (!apiKey) { setErrorMsg(Please enter your DashScope API Key first.); return; } setStatus(submitting); setErrorMsg(); setResultUrl(); setLogs([]); setProgress(0); // 1. Construct Request const headers { Authorization: Bearer ${apiKey}, Content-Type: application/json, X-DashScope-Async: enable // Important for video generation }; const payload { model: model, input: { prompt: prompt, negative_prompt: negativePrompt }, parameters: { size: resolution, duration: parseInt(duration), // seed: Math.floor(Math.random() * 1000000) // Optional } }; addLog(req, Submitting Task..., payload); try { // NOTE: In a real browser environment, calling DashScope directly might trigger CORS errors. // This code assumes the environment supports it or a proxy is used. // For the artifact demo, we will simulate the flow if it fails due to CORS, // but the code structure is correct for a backend/proxy setup. const submitResponse await fetch(https://dashscope.aliyuncs.com/api/v1/services/aigc/video-generation/generation, { method: POST, headers: headers, body: JSON.stringify(payload) }); if (!submitResponse.ok) { const errorData await submitResponse.json(); throw new Error(errorData.message || HTTP Error: ${submitResponse.status}); } const submitData await submitResponse.json(); addLog(res, Task Submitted Successfully, submitData); if (submitData.output submitData.output.task_id) { const newTaskId submitData.output.task_id; setTaskId(newTaskId); setStatus(polling); startPolling(newTaskId, headers); } else { throw new Error(No task_id received); } } catch (err) { console.error(err); setStatus(error); setErrorMsg(err.message); addLog(err, Submission Failed, err.message); // CORS Hint for user if (err.message.includes(Failed to fetch) || err.message.includes(NetworkError)) { addLog(info, CORS WARNING: Direct browser calls to DashScope are often blocked. You may need a backend proxy or a browser extension to allow CORS.); } } }; const startPolling (tid, headers) { let attempts 0; pollInterval.current setInterval(async () { attempts; try { const pollUrl https://dashscope.aliyuncs.com/api/v1/tasks/${tid}; const pollRes await fetch(pollUrl, { method: GET, headers: headers }); if (!pollRes.ok) throw new Error(Polling Error: ${pollRes.status}); const pollData await pollRes.json(); const taskStatus pollData.output.task_status; addLog(poll, Status: ${taskStatus} (Attempt ${attempts}), pollData); if (taskStatus SUCCEEDED) { clearInterval(pollInterval.current); setStatus(success); if (pollData.output.video_url) { setResultUrl(pollData.output.video_url); } addLog(success, Generation Complete!, pollData.output); } else if (taskStatus FAILED || taskStatus CANCELED) { clearInterval(pollInterval.current); setStatus(error); setErrorMsg(pollData.output.message || Task Failed); } else { // RUNNING or PENDING // Simulate progress since API doesnt always return percentage setProgress(prev Math.min(prev 5, 95)); } } catch (err) { addLog(err, Polling Error, err.message); // Dont stop polling immediately on network glitch, but stop after too many fails if (attempts 60) { clearInterval(pollInterval.current); setStatus(error); setErrorMsg(Polling timed out); } } }, 3000); // Poll every 3 seconds }; const copyToClipboard (text) { navigator.clipboard.writeText(text); }; return ( div classNamemin-h-screen bg-slate-50 p-4 md:p-8 font-sans text-slate-900 div classNamemax-w-7xl mx-auto grid grid-cols-1 lg:grid-cols-3 gap-6 {/* Header */} div classNamelg:col-span-3 flex items-center justify-between mb-2 div h1 classNametext-2xl font-bold flex items-center gap-2 Play classNameh-6 w-6 text-purple-600 / Tongyi Wan API Studio /h1 p classNametext-slate-500 text-smVisual interface for Alibaba Cloud Wan Video Generation Models/p /div div classNameflex gap-2 Badge variantoutline classNamebg-whitev1.0.0/Badge /div /div {/* Left Column: Controls */} div classNamelg:col-span-1 space-y-6 {/* API Key Config */} Card classNameborder-slate-200 shadow-sm CardHeader classNamepb-3 CardTitle classNametext-sm font-medium uppercase tracking-wider text-slate-500 flex items-center gap-2 Settings classNameh-4 w-4 / Configuration /CardTitle /CardHeader CardContent classNamespace-y-4 div classNamespace-y-2 Label htmlForapiKeyDashScope API Key/Label div classNamerelative Input idapiKey type{showKey ? text : password} placeholdersk-... value{apiKey} onChange{(e) setApiKey(e.target.value)} classNamepr-10 / button onClick{() setShowKey(!showKey)} classNameabsolute right-2 top-2.5 text-slate-400 hover:text-slate-600 {showKey ? EyeOff classNameh-4 w-4 / : Eye classNameh-4 w-4 /} /button /div p classNametext-xs text-slate-400 Key is stored in memory only. Never shared. /p /div /CardContent /Card {/* Generation Controls */} Card classNameborder-slate-200 shadow-sm h-fit CardHeader classNamepb-3 CardTitle classNametext-sm font-medium uppercase tracking-wider text-slate-500 flex items-center gap-2 Play classNameh-4 w-4 / Parameters /CardTitle /CardHeader CardContent classNamespace-y-4 div classNamespace-y-2 LabelModel Version/Label Select value{model} onValueChange{setModel} SelectTrigger SelectValue placeholderSelect Model / /SelectTrigger SelectContent SelectItem valuewan2.1-t2v-pluswan2.1-t2v-plus (Flagship)/SelectItem SelectItem valuewan2.1-t2v-turbowan2.1-t2v-turbo (Fast)/SelectItem SelectItem valuewan2.0-t2v-turbowan2.0-t2v-turbo/SelectItem /SelectContent /Select /div div classNamespace-y-2 LabelResolution/Label Select value{resolution} onValueChange{setResolution} SelectTrigger SelectValue / /SelectTrigger SelectContent SelectItem value1280*7201280x720 (Landscape)/SelectItem SelectItem value720*1280720x1280 (Portrait)/SelectItem SelectItem value1024*10241024x1024 (Square)/SelectItem /SelectContent /Select /div div classNamespace-y-2 LabelDuration (Seconds)/Label Select value{duration} onValueChange{setDuration} SelectTrigger SelectValue / /SelectTrigger SelectContent SelectItem value55 Seconds/SelectItem /SelectContent /Select /div div classNamespace-y-2 LabelPrompt/Label Textarea placeholderDescribe your video... classNamemin-h-[100px] resize-none value{prompt} onChange{(e) setPrompt(e.target.value)} / /div div classNamespace-y-2 LabelNegative Prompt/Label Input placeholderWhat to avoid... value{negativePrompt} onChange{(e) setNegativePrompt(e.target.value)} / /div Button classNamew-full bg-purple-600 hover:bg-purple-700 text-white onClick{handleGenerate} disabled{status submitting || status polling} {status submitting || status polling ? ( Loader2 classNamemr-2 h-4 w-4 animate-spin / Generating.../ ) : ( Play classNamemr-2 h-4 w-4 / Generate Video/ )} /Button /CardContent /Card /div {/* Right Column: Preview Logs */} div classNamelg:col-span-2 space-y-6 {/* Preview Area */} Card classNameborder-slate-200 shadow-sm min-h-[400px] flex flex-col CardHeader classNamepb-3 border-b border-slate-100 div classNameflex justify-between items-center CardTitle classNametext-sm font-medium uppercase tracking-wider text-slate-500 flex items-center gap-2 ImageIcon classNameh-4 w-4 / Preview /CardTitle {status polling ( Badge variantsecondary classNameanimate-pulseProcessing... {progress}%/Badge )} {status success ( Badge classNamebg-green-500 hover:bg-green-600Completed/Badge )} /div /CardHeader CardContent classNameflex-1 flex items-center justify-center bg-slate-100/50 p-0 relative overflow-hidden {status idle ( div classNametext-center text-slate-400 Play classNameh-12 w-12 mx-auto mb-2 opacity-20 / pReady to generate/p /div )} {(status submitting || status polling) ( div classNametext-center space-y-4 div classNamerelative h-24 w-24 mx-auto div classNameabsolute inset-0 border-4 border-purple-200 rounded-full/div div classNameabsolute inset-0 border-4 border-purple-600 rounded-full border-t-transparent animate-spin/div /div div p classNamefont-medium text-slate-700AI is dreaming.../p p classNametext-sm text-slate-400Task ID: {taskId}/p /div /div )} {status error ( div classNametext-center text-red-500 p-6 AlertCircle classNameh-12 w-12 mx-auto mb-2 / p classNamefont-mediumGeneration Failed/p p classNametext-sm mt-2 bg-red-50 p-2 rounded border border-red-100{errorMsg}/p /div )} {status success resultUrl ( div classNamew-full h-full flex flex-col video controls autoPlay loop classNamew-full h-full object-contain bg-black src{resultUrl} / /div )} /CardContent {status success resultUrl ( CardFooter classNamebg-white border-t border-slate-100 p-3 flex justify-end Button variantoutline sizesm onClick{() window.open(resultUrl, _blank)} Download Video /Button /CardFooter )} /Card {/* Logs Console */} Card classNameborder-slate-200 shadow-sm flex-1 flex flex-col CardHeader classNamepb-3 bg-slate-900 text-slate-200 rounded-t-lg CardTitle classNametext-sm font-mono flex items-center gap-2 Terminal classNameh-4 w-4 / API Console / Logs /CardTitle /CardHeader CardContent classNamep-0 bg-slate-950 ScrollArea classNameh-[250px] w-full p-4 font-mono text-xs {logs.length 0 ? ( span classNametext-slate-600// Waiting for requests.../span ) : ( logs.map((log, i) ( div key{i} classNamemb-3 border-b border-slate-800/50 pb-2 last:border-0 div classNameflex gap-2 mb-1 span classNametext-slate-500[{log.time}]/span span className{font-bold ${ log.type req ? text-blue-400 : log.type res ? text-green-400 : log.type err ? text-red-400 : text-yellow-400 }} {log.type.toUpperCase()} /span span classNametext-slate-300{log.message}/span /div {log.data ( pre classNametext-slate-500 overflow-x-auto bg-slate-900/50 p-2 rounded {JSON.stringify(log.data, null, 2)} /pre )} /div )) )} /ScrollArea /CardContent /Card /div /div /div ); }; export default WanDashboard;使用说明与注意事项关于 CORS跨域报错现象如果你直接在浏览器运行上述代码并点击生成可能会在控制台看到Access-Control-Allow-Origin相关的红色报错。原因阿里云 DashScope API 出于安全考虑默认不允许纯浏览器前端直接发起调用防止你的 API Key 暴露在公网。解决方案本地测试你可以安装 Chrome 插件如 “Allow CORS”临时绕过限制进行测试。正式使用你需要一个简单的后端Node.js/Python作为中转或者使用 Next.js 的 API Route。模型版本代码中预置了wan2.1-t2v-plus这是目前的旗舰视频模型。如果官方发布了更新的版本如你提到的 2.6你只需在左侧下拉菜单选择或直接修改代码中的model参数即可。如何获取 API Key访问 阿里云百炼控制台。开通 DashScope 服务并创建一个 API Key。将 Key 粘贴到面板左上角的配置框中即可。这个面板展示了不使用任何第三方套壳工具仅用标准的 Web 技术React fetch即可完成与大模型的深度交互。