'use client' import { useState, useEffect } from 'react' import { useRouter, useParams, useSearchParams } from 'next/navigation' import { useToast } from '@/components/ui/Toast' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card' import { Button } from '@/components/ui/Button' import { SuccessTag, WarningTag, ErrorTag, PendingTag } from '@/components/ui/Tag' import { ReviewSteps, getReviewSteps } from '@/components/ui/ReviewSteps' import { ArrowLeft, Upload, FileText, CheckCircle, XCircle, AlertTriangle, Clock, Loader2, RefreshCw, Eye, MessageSquare, Download, File, Target, Ban, ChevronDown, ChevronUp } from 'lucide-react' import { Modal } from '@/components/ui/Modal' // 代理商Brief文档(达人可查看) type AgencyBriefFile = { id: string name: string size: string uploadedAt: string description?: string } const mockAgencyBrief = { // 代理商上传的Brief文档 files: [ { id: 'af1', name: '达人拍摄指南.pdf', size: '1.5MB', uploadedAt: '2026-02-02', description: '详细的拍摄流程和注意事项' }, { id: 'af2', name: '产品卖点话术.docx', size: '800KB', uploadedAt: '2026-02-02', description: '推荐使用的话术和表达方式' }, { id: 'af3', name: '品牌视觉参考.pdf', size: '3.2MB', uploadedAt: '2026-02-02', description: '视觉风格和拍摄参考示例' }, ] as AgencyBriefFile[], // 卖点要求 sellingPoints: [ { id: 'sp1', content: 'SPF50+ PA++++', required: true }, { id: 'sp2', content: '轻薄质地,不油腻', required: true }, { id: 'sp3', content: '延展性好,易推开', required: false }, { id: 'sp4', content: '适合敏感肌', required: false }, { id: 'sp5', content: '夏日必备防晒', required: true }, ], // 违禁词 blacklistWords: [ { id: 'bw1', word: '最好', reason: '绝对化用语' }, { id: 'bw2', word: '第一', reason: '绝对化用语' }, { id: 'bw3', word: '神器', reason: '夸大宣传' }, { id: 'bw4', word: '完美', reason: '绝对化用语' }, ], } // 模拟任务数据 const mockTask = { id: 'task-001', projectName: 'XX品牌618推广', brandName: 'XX护肤品牌', deadline: '2026-06-18', scriptStatus: 'pending_upload', // pending_upload | ai_reviewing | ai_result | agent_reviewing | agent_rejected | brand_reviewing | brand_passed | brand_rejected scriptFile: null as string | null, aiResult: null as null | { score: number violations: Array<{ type: string; content: string; suggestion: string }> complianceChecks: Array<{ item: string; passed: boolean; note?: string }> }, agencyReview: null as null | { result: 'approved' | 'rejected' comment: string reviewer: string time: string }, brandReview: null as null | { result: 'approved' | 'rejected' comment: string reviewer: string time: string }, } // 根据状态获取模拟数据 function getTaskByStatus(status: string) { const task = { ...mockTask, scriptStatus: status } if (status === 'ai_result' || status === 'agent_reviewing' || status === 'agent_rejected' || status === 'brand_reviewing' || status === 'brand_passed' || status === 'brand_rejected') { task.scriptFile = '夏日护肤推广脚本.docx' task.aiResult = { score: 85, violations: [ { type: '违禁词', content: '神器', suggestion: '建议替换为"好物"或"必备品"' }, ], complianceChecks: [ { item: '品牌名称正确', passed: true }, { item: 'SPF标注准确', passed: true }, { item: '无绝对化用语', passed: false, note: '"超级好用"建议修改' }, ], } } if (status === 'agent_rejected') { task.agencyReview = { result: 'rejected', comment: '违禁词未修改,请修改后重新提交。', reviewer: '张经理', time: '2026-02-06 15:30', } } if (status === 'brand_reviewing' || status === 'brand_passed' || status === 'brand_rejected') { task.agencyReview = { result: 'approved', comment: '脚本符合要求,建议通过。', reviewer: '张经理', time: '2026-02-06 15:30', } } if (status === 'brand_passed') { task.brandReview = { result: 'approved', comment: '脚本通过终审,可以开始拍摄视频。', reviewer: '品牌方审核员', time: '2026-02-06 18:00', } } if (status === 'brand_rejected') { task.brandReview = { result: 'rejected', comment: '产品卖点覆盖不完整,请补充后重新提交。', reviewer: '品牌方审核员', time: '2026-02-06 18:00', } } return task } // 代理商Brief文档查看组件 function AgencyBriefSection({ toast }: { toast: ReturnType }) { const [isExpanded, setIsExpanded] = useState(true) const [previewFile, setPreviewFile] = useState(null) const handleDownload = (file: AgencyBriefFile) => { toast.info(`下载文件: ${file.name}`) } const handlePreview = (file: AgencyBriefFile) => { setPreviewFile(file) } const requiredPoints = mockAgencyBrief.sellingPoints.filter(sp => sp.required) const optionalPoints = mockAgencyBrief.sellingPoints.filter(sp => !sp.required) return ( <> Brief 文档与要求 {isExpanded && ( {/* Brief文档列表 */}

参考文档

{mockAgencyBrief.files.map((file) => (

{file.name}

{file.size}

))}
{/* 卖点要求 */}

卖点要求

{requiredPoints.length > 0 && (

必选卖点(必须提及)

{requiredPoints.map((sp) => ( {sp.content} ))}
)} {optionalPoints.length > 0 && (

可选卖点

{optionalPoints.map((sp) => ( {sp.content} ))}
)}
{/* 违禁词 */}

违禁词(请勿使用)

{mockAgencyBrief.blacklistWords.map((bw) => ( 「{bw.word}」 ))}
)}
{/* 文件预览弹窗 */} setPreviewFile(null)} title={previewFile?.name || '文件预览'} size="lg" >

文件预览区域

实际开发中将嵌入文件预览组件

{previewFile && ( )}
) } function UploadSection({ onUpload }: { onUpload: () => void }) { const [file, setFile] = useState(null) const handleFileChange = (e: React.ChangeEvent) => { const selectedFile = e.target.files?.[0] if (selectedFile) { setFile(selectedFile) } } return ( 上传脚本
{file ? (
{file.name}
) : ( )}
) } function AIReviewingSection() { const [progress, setProgress] = useState(0) const [logs, setLogs] = useState(['开始解析脚本文件...']) useEffect(() => { const timer = setInterval(() => { setProgress(prev => { if (prev >= 100) { clearInterval(timer) return 100 } return prev + 10 }) }, 500) const logTimer = setTimeout(() => { setLogs(prev => [...prev, '正在提取文本内容...']) }, 1000) const logTimer2 = setTimeout(() => { setLogs(prev => [...prev, '正在进行违禁词检测...']) }, 2000) const logTimer3 = setTimeout(() => { setLogs(prev => [...prev, '正在分析卖点覆盖...']) }, 3000) return () => { clearInterval(timer) clearTimeout(logTimer) clearTimeout(logTimer2) clearTimeout(logTimer3) } }, []) return (

AI 正在审核您的脚本

请稍候,预计需要 1-2 分钟

{progress}%

处理日志

{logs.map((log, idx) => (

{log}

))}
) } function AIResultSection({ task }: { task: ReturnType }) { if (!task.aiResult) return null return ( AI 审核结果 = 85 ? 'text-accent-green' : task.aiResult.score >= 70 ? 'text-yellow-400' : 'text-accent-coral'}`}> {task.aiResult.score}分 {/* 违规检测 */} {task.aiResult.violations.length > 0 && (

违规检测 ({task.aiResult.violations.length})

{task.aiResult.violations.map((v, idx) => (
{v.type}

「{v.content}」

{v.suggestion}

))}
)} {/* 合规检查 */}

合规检查

{task.aiResult.complianceChecks.map((check, idx) => (
{check.passed ? ( ) : ( )}
{check.item} {check.note &&

{check.note}

}
))}
) } function ReviewFeedbackSection({ review, type }: { review: NonNullable; type: 'agency' | 'brand' }) { const isApproved = review.result === 'approved' const title = type === 'agency' ? '代理商审核意见' : '品牌方终审意见' return ( {isApproved ? ( ) : ( )} {title}
{review.reviewer} {isApproved ? 通过 : 驳回}

{review.comment}

{review.time}

) } function WaitingSection({ message }: { message: string }) { return (

{message}

请耐心等待,审核结果将通过消息通知您

) } function SuccessSection({ onContinue }: { onContinue: () => void }) { return (

脚本审核通过!

您可以开始拍摄视频了

) } export default function CreatorScriptPage() { const router = useRouter() const params = useParams() const searchParams = useSearchParams() const toast = useToast() const status = searchParams.get('status') || 'pending_upload' const [task, setTask] = useState(getTaskByStatus(status)) // 模拟状态切换 const simulateUpload = () => { setTask(getTaskByStatus('ai_reviewing')) setTimeout(() => { setTask(getTaskByStatus('ai_result')) }, 4000) } const handleResubmit = () => { setTask(getTaskByStatus('pending_upload')) } const handleContinueToVideo = () => { router.push(`/creator/task/${params.id}/video`) } const getStatusDisplay = () => { switch (task.scriptStatus) { case 'pending_upload': return '待上传脚本' case 'ai_reviewing': return 'AI 审核中' case 'ai_result': return 'AI 审核完成' case 'agent_reviewing': return '代理商审核中' case 'agent_rejected': return '代理商驳回' case 'brand_reviewing': return '品牌方终审中' case 'brand_passed': return '审核通过' case 'brand_rejected': return '品牌方驳回' default: return '未知状态' } } return (
{/* 顶部导航 */}

{task.projectName}

脚本阶段 · {getStatusDisplay()}

{/* 审核流程进度条 */} {/* Brief文档与要求(始终显示) */} {/* 根据状态显示不同内容 */} {task.scriptStatus === 'pending_upload' && ( )} {task.scriptStatus === 'ai_reviewing' && ( )} {task.scriptStatus === 'ai_result' && ( <> )} {task.scriptStatus === 'agent_reviewing' && ( <> )} {task.scriptStatus === 'agent_rejected' && task.agencyReview && ( <>
)} {task.scriptStatus === 'brand_reviewing' && task.agencyReview && ( <> )} {task.scriptStatus === 'brand_passed' && task.agencyReview && task.brandReview && ( <> )} {task.scriptStatus === 'brand_rejected' && task.agencyReview && task.brandReview && ( <>
)}
) }