"use client"; import { useState, useEffect } from "react"; import Link from "next/link"; // 动态获取 API 地址:服务端使用 localhost,客户端使用当前域名 const API_BASE = typeof window !== 'undefined' ? `http://${window.location.hostname}:8006` : 'http://localhost:8006'; interface Account { platform: string; name: string; logged_in: boolean; enabled: boolean; } interface Video { name: string; path: string; } export default function PublishPage() { const [accounts, setAccounts] = useState([]); const [videos, setVideos] = useState([]); const [selectedVideo, setSelectedVideo] = useState(""); const [selectedPlatforms, setSelectedPlatforms] = useState([]); const [title, setTitle] = useState(""); const [tags, setTags] = useState(""); const [isPublishing, setIsPublishing] = useState(false); const [publishResults, setPublishResults] = useState([]); // 加载账号和视频列表 useEffect(() => { fetchAccounts(); fetchVideos(); }, []); const fetchAccounts = async () => { try { const res = await fetch(`${API_BASE}/api/publish/accounts`); const data = await res.json(); setAccounts(data.accounts || []); } catch (error) { console.error("获取账号失败:", error); } }; const fetchVideos = async () => { try { // 获取已生成的视频列表 (从 outputs 目录) const res = await fetch(`${API_BASE}/api/videos/tasks`); const data = await res.json(); const completedVideos = data.tasks ?.filter((t: any) => t.status === "completed") .map((t: any) => ({ name: `${t.task_id}_output.mp4`, path: `outputs/${t.task_id}_output.mp4`, })) || []; setVideos(completedVideos); if (completedVideos.length > 0) { setSelectedVideo(completedVideos[0].path); } } catch (error) { console.error("获取视频失败:", error); } }; const togglePlatform = (platform: string) => { if (selectedPlatforms.includes(platform)) { setSelectedPlatforms(selectedPlatforms.filter((p) => p !== platform)); } else { setSelectedPlatforms([...selectedPlatforms, platform]); } }; const handlePublish = async () => { if (!selectedVideo || !title || selectedPlatforms.length === 0) { alert("请选择视频、填写标题并选择至少一个平台"); return; } setIsPublishing(true); setPublishResults([]); const tagList = tags.split(/[,,\s]+/).filter((t) => t.trim()); for (const platform of selectedPlatforms) { try { const res = await fetch(`${API_BASE}/api/publish/`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ video_path: selectedVideo, platform, title, tags: tagList, description: "", }), }); const result = await res.json(); setPublishResults((prev) => [...prev, result]); } catch (error) { setPublishResults((prev) => [ ...prev, { platform, success: false, message: String(error) }, ]); } } setIsPublishing(false); }; const handleLogin = async (platform: string) => { alert( `登录功能需要在服务端执行。\n\n请在终端运行:\ncurl -X POST http://localhost:8006/api/publish/login/${platform}` ); }; const platformIcons: Record = { douyin: "🎵", xiaohongshu: "📕", weixin: "💬", kuaishou: "⚡", bilibili: "📺", }; return (
{/* Header */}
🎬 TalkingHead Agent

📤 社交媒体发布

{/* 左侧: 账号管理 */}

👤 平台账号

{accounts.map((account) => (
{platformIcons[account.platform]}
{account.name}
{account.logged_in ? "✓ 已登录" : "未登录"}
))}
{/* 右侧: 发布表单 */}
{/* 选择视频 */}

🎥 选择要发布的视频

{videos.length === 0 ? (

暂无已生成的视频,请先 生成视频

) : ( )}
{/* 填写信息 */}

✍️ 发布信息

setTitle(e.target.value)} placeholder="输入视频标题..." className="w-full p-3 bg-black/30 border border-white/10 rounded-xl text-white placeholder-gray-500" />
setTags(e.target.value)} placeholder="AI, 数字人, 口播..." className="w-full p-3 bg-black/30 border border-white/10 rounded-xl text-white placeholder-gray-500" />
{/* 选择平台 */}

📱 选择发布平台

{accounts .filter((a) => a.logged_in) .map((account) => ( ))}
{accounts.filter((a) => a.logged_in).length === 0 && (

请先登录至少一个平台账号

)}
{/* 发布按钮 */} {/* 发布结果 */} {publishResults.length > 0 && (

发布结果

{publishResults.map((result, i) => (
{platformIcons[result.platform]} {result.message}
))}
)}
); }