"use client"; import { useState, useEffect } from "react"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Skeleton } from "@/components/ui/skeleton"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Tabs, TabsContent, TabsList, TabsTrigger, } from "@/components/ui/tabs"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Send, CheckCircle, AlertCircle, XCircle, ChevronDown, ChevronUp, Eye, Clock, Tag, AlertTriangle, Check, RefreshCw, Globe, Settings, } from "lucide-react"; import { distributionApi, analyticsApi, type PlatformInfo, type PublishRecordResponse, } from "@/lib/api"; // ─── Types ─────────────────────────────────────────────────────────────────── type ValidationResult = "pass" | "warn" | "fail"; interface PlatformValidation { platform: string; result: ValidationResult; message: string; } // ─── Helpers ───────────────────────────────────────────────────────────────── const PLATFORM_COLOR_MAP: Record = { wechat: { label: "微信", color: "text-green-700", bg: "bg-green-100" }, zhihu: { label: "知乎", color: "text-blue-700", bg: "bg-blue-100" }, xiaohongshu: { label: "小红书", color: "text-red-700", bg: "bg-red-100" }, douyin: { label: "抖音", color: "text-slate-700", bg: "bg-slate-100" }, baijiahao: { label: "百家号", color: "text-orange-700", bg: "bg-orange-100" }, weibo: { label: "微博", color: "text-red-600", bg: "bg-red-100" }, general: { label: "通用", color: "text-gray-700", bg: "bg-gray-100" }, }; function getPlatformConfig(platformId: string) { return PLATFORM_COLOR_MAP[platformId] ?? { label: platformId, color: "text-gray-700", bg: "bg-gray-100" }; } function ValidationIcon({ result }: { result: ValidationResult }) { switch (result) { case "pass": return ; case "warn": return ; case "fail": return ; } } function PlatformAvatar({ platformId, name }: { platformId: string; name: string }) { const config = getPlatformConfig(platformId); return ( {(name || config.label).charAt(0)} ); } function getPublishedStatusConfig(status: string) { switch (status) { case "published": return { label: "发布成功", className: "bg-emerald-50 text-emerald-600 border-emerald-200" }; case "failed": return { label: "发布失败", className: "bg-red-50 text-red-600 border-red-200" }; case "pending": return { label: "待发布", className: "bg-amber-50 text-amber-600 border-amber-200" }; default: return { label: status, className: "bg-gray-50 text-gray-600 border-gray-200" }; } } // ─── Sub-components ────────────────────────────────────────────────────────── function PlatformCard({ platform }: { platform: PlatformInfo }) { const [expanded, setExpanded] = useState(false); const config = getPlatformConfig(platform.id); const validations: PlatformValidation[] = [ { platform: platform.id, result: "pass", message: `最大标题长度:${platform.max_title_length} 字`, }, { platform: platform.id, result: platform.max_content_length >= 1000 ? "pass" : "warn", message: `内容长度限制:${platform.min_content_length}–${platform.max_content_length} 字`, }, { platform: platform.id, result: platform.format_features?.supports_markdown ? "pass" : "warn", message: platform.format_features?.supports_markdown ? "支持 Markdown 格式" : "不支持 Markdown,需转换格式", }, ]; return (
{/* Title + Avatar */}

{platform.name}

{platform.max_content_length.toLocaleString()} 字上限

已配置
{/* Best publish times */} {platform.best_publish_times.length > 0 && (
最佳发布时段:{platform.best_publish_times.slice(0, 3).join("、")}
)} {/* SEO tips preview */} {platform.seo_tips.length > 0 && (
💡 {platform.seo_tips[0]}
)} {/* Expandable rules */} {expanded && (
{validations.map((v, idx) => (
{v.message}
))} {platform.rules.slice(0, 3).map((rule, idx) => (
{rule}
))}
)} {/* Tags */} {platform.supported_media.length > 0 && (
{platform.supported_media.slice(0, 3).map((media) => ( {media} ))}
)}
); } function EmptyPlatforms() { return (

暂无平台配置

后端暂无平台规则数据,请检查后端服务状态

); } function EmptyPublished() { return (

暂无发布记录

在内容工坊生成内容并发布后,记录将在此显示

); } // ─── Main Page ─────────────────────────────────────────────────────────────── export default function DistributionPage() { const [platforms, setPlatforms] = useState([]); const [publishRecords, setPublishRecords] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); // Strategy dialog const [strategyOpen, setStrategyOpen] = useState(false); const [activePlatform, setActivePlatform] = useState(null); useEffect(() => { async function fetchData() { try { setLoading(true); setError(null); const [platformsData, recordsData] = await Promise.all([ distributionApi.getPlatforms(), // Use analytics publish endpoint to get publish records analyticsApi.getTopContent(undefined, { limit: 20 }) .then((r) => r?.items ?? []) .catch(() => []), ]); setPlatforms(platformsData?.platforms ?? []); // Convert top content to publish-record-like shape for display setPublishRecords( recordsData.map((item) => ({ id: item.publish_record_id, organization_id: "", content_title: item.content_title, content_id: null, platform: item.platform, published_url: item.published_url, status: "published", published_at: item.recorded_at, created_at: item.recorded_at ?? "", })) ); } catch (err) { console.error("Distribution fetch error:", err); setError(err instanceof Error ? err.message : "数据加载失败"); } finally { setLoading(false); } } fetchData(); }, []); const handleViewStrategy = (platform: PlatformInfo) => { setActivePlatform(platform); setStrategyOpen(true); }; if (loading) { return (
{Array.from({ length: 3 }).map((_, i) => ( ))}
); } return (
{/* Top Area */}

内容分发中心

多平台智能分发与发布管理

{/* Error Banner */} {error && (
{error}
)} {/* Tabs */} 平台规则 ({platforms.length}) 发布记录 ({publishRecords.length}) {/* Platforms Tab */} {platforms.length === 0 ? ( ) : (
{platforms.map((platform) => (
))}
)}
{/* Published Records Tab */} {publishRecords.length === 0 ? ( ) : ( 标题 平台 发布时间 状态 {publishRecords.map((item) => { const statusConfig = getPublishedStatusConfig(item.status); const platformConfig = getPlatformConfig(item.platform); const publishedAt = item.published_at ? new Date(item.published_at).toLocaleString("zh-CN") : "—"; return ( {item.content_title} {platformConfig.label} {publishedAt} {statusConfig.label} ); })}
)}
{/* Platform Strategy Dialog */} {activePlatform?.name} 发布策略 基于平台特性的最佳发布方案 {activePlatform && (
{/* Best times */} {activePlatform.best_publish_times.length > 0 && (

最佳发布时段

{activePlatform.best_publish_times.map((time) => ( {time} ))}
{activePlatform.best_publish_days.length > 0 && (

推荐日期:{activePlatform.best_publish_days.join("、")}

)}
)} {/* SEO Tips */} {activePlatform.seo_tips.length > 0 && (

SEO 优化建议

    {activePlatform.seo_tips.map((tip, idx) => (
  • {tip}
  • ))}
)} {/* Rules */} {activePlatform.rules.length > 0 && (

发布规则

    {activePlatform.rules.map((rule, idx) => (
  • {rule}
  • ))}
)}
)}
); }