'use client' import { useState } from 'react' import { useRouter, useParams } from 'next/navigation' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card' import { Button } from '@/components/ui/Button' import { Modal, ConfirmModal } from '@/components/ui/Modal' import { SuccessTag, WarningTag, ErrorTag } from '@/components/ui/Tag' import { ReviewSteps, getAgencyReviewSteps } from '@/components/ui/ReviewSteps' import { ArrowLeft, Play, Pause, AlertTriangle, Shield, Radio, User, Clock, CheckCircle, XCircle, Download, ExternalLink, MessageSquareWarning } from 'lucide-react' import { FileInfoCard, FilePreviewModal, type FileInfo } from '@/components/ui/FilePreview' // 模拟视频任务数据 const mockVideoTask = { id: 'video-001', title: '夏日护肤推广', creatorName: '小美护肤', projectName: 'XX品牌618推广', submittedAt: '2026-02-06 15:00', duration: 135, aiScore: 85, status: 'agent_reviewing', // 文件信息 file: { id: 'file-video-001', fileName: '夏日护肤_成片v2.mp4', fileSize: '128 MB', fileType: 'video/mp4', fileUrl: '/demo/videos/video-001.mp4', // 实际开发时替换为真实URL uploadedAt: '2026-02-06 15:00', duration: '02:15', thumbnail: '/demo/videos/video-001-thumb.jpg', } as FileInfo, // 申诉信息 isAppeal: false, appealReason: '', hardViolations: [ { id: 'v1', type: '违禁词', content: '效果最好', timestamp: 15.5, source: 'speech', riskLevel: 'high', aiConfidence: 0.95, suggestion: '建议替换为"效果显著"', }, { id: 'v2', type: '竞品露出', content: '疑似竞品Logo', timestamp: 42.0, source: 'visual', riskLevel: 'medium', aiConfidence: 0.72, suggestion: '需人工确认是否为竞品露出', }, ], sentimentWarnings: [ { id: 's1', type: '油腻预警', timestamp: 68.0, content: '达人表情过于夸张,建议检查', riskLevel: 'medium' }, ], sellingPointsCovered: [ { point: 'SPF50+ PA++++', covered: true, timestamp: 25.0 }, { point: '轻薄质地', covered: true, timestamp: 38.0 }, { point: '不油腻', covered: true, timestamp: 52.0 }, { point: '延展性好', covered: true, timestamp: 45.0 }, ], } function formatTimestamp(seconds: number): string { const mins = Math.floor(seconds / 60) const secs = Math.floor(seconds % 60) return `${mins}:${secs.toString().padStart(2, '0')}` } function ReviewProgressBar({ taskStatus }: { taskStatus: string }) { const steps = getAgencyReviewSteps(taskStatus) const currentStep = steps.find(s => s.status === 'current') return (
审核流程 当前:{currentStep?.label || '代理商审核'}
) } function RiskLevelTag({ level }: { level: string }) { if (level === 'high') return 高风险 if (level === 'medium') return 中风险 return 低风险 } export default function AgencyVideoReviewPage() { const router = useRouter() const params = useParams() const [isPlaying, setIsPlaying] = useState(false) const [showApproveModal, setShowApproveModal] = useState(false) const [showRejectModal, setShowRejectModal] = useState(false) const [showForcePassModal, setShowForcePassModal] = useState(false) const [rejectReason, setRejectReason] = useState('') const [forcePassReason, setForcePassReason] = useState('') const [saveAsException, setSaveAsException] = useState(false) const [checkedViolations, setCheckedViolations] = useState>({}) const [showFilePreview, setShowFilePreview] = useState(false) const [videoError, setVideoError] = useState(false) const task = mockVideoTask const handleApprove = () => { setShowApproveModal(false) alert('已提交品牌方终审!') router.push('/agency/review') } const handleReject = () => { if (!rejectReason.trim()) { alert('请填写驳回原因') return } setShowRejectModal(false) alert('已驳回') router.push('/agency/review') } const handleForcePass = () => { if (!forcePassReason.trim()) { alert('请填写强制通过原因') return } setShowForcePassModal(false) alert('已强制通过并提交品牌方终审!') router.push('/agency/review') } // 计算问题时间点用于进度条展示 const timelineMarkers = [ ...task.hardViolations.map(v => ({ time: v.timestamp, type: 'hard' as const })), ...task.sentimentWarnings.map(w => ({ time: w.timestamp, type: 'soft' as const })), ...task.sellingPointsCovered.filter(s => s.covered).map(s => ({ time: s.timestamp, type: 'selling' as const })), ].sort((a, b) => a.time - b.time) return (
{/* 顶部导航 */}

{task.title}

{task.isAppeal && ( 申诉 )}
{task.creatorName} {task.submittedAt}
{/* 申诉理由 */} {task.isAppeal && task.appealReason && (

申诉理由

{task.appealReason}

)} {/* 审核流程进度条 */}
{/* 左侧:视频播放器 (3/5) */}
{/* 文件信息卡片 */} setShowFilePreview(true)} /> {/* 真实视频播放器 */}
{videoError ? (

视频加载失败

) : ( )}
{/* 智能进度条 */}
智能进度条(点击跳转)
{/* 时间标记点 */} {timelineMarkers.map((marker, idx) => (
0:00 {formatTimestamp(task.duration)}
硬性问题 舆情提示 卖点覆盖
{/* AI 分析总结 */}
AI 分析总结 = 80 ? 'text-accent-green' : 'text-yellow-400'}`}> {task.aiScore}分

视频整体合规,发现{task.hardViolations.length}处硬性问题和{task.sentimentWarnings.length}处舆情提示需人工确认

{/* 右侧:AI 检查单 (2/5) */}
{/* 硬性合规 */} 硬性合规 ({task.hardViolations.length}) {task.hardViolations.map((v) => (
setCheckedViolations((prev) => ({ ...prev, [v.id]: !prev[v.id] }))} className="mt-1 accent-accent-indigo" />
{v.type} {formatTimestamp(v.timestamp)}

「{v.content}」

{v.suggestion}

))}
{/* 舆情雷达 */} {task.sentimentWarnings.length > 0 && ( 舆情雷达(仅提示) {task.sentimentWarnings.map((w) => (
{w.type} {formatTimestamp(w.timestamp)}

{w.content}

⚠️ 软性风险仅作提示,不强制拦截

))}
)} {/* 卖点覆盖 */} 卖点覆盖 {task.sellingPointsCovered.map((sp, idx) => (
{sp.covered ? ( ) : ( )} {sp.point}
{sp.covered && ( {formatTimestamp(sp.timestamp)} )}
))}
{/* 底部决策栏 */}
已检查 {Object.values(checkedViolations).filter(Boolean).length}/{task.hardViolations.length} 个问题
{/* 通过确认弹窗 */} setShowApproveModal(false)} onConfirm={handleApprove} title="确认通过" message="确定要通过此视频的审核吗?通过后将提交给品牌方进行终审。" confirmText="确认通过" /> {/* 驳回弹窗 */} setShowRejectModal(false)} title="驳回审核">

请填写驳回原因,已勾选的问题将自动打包发送给达人。

已选问题 ({Object.values(checkedViolations).filter(Boolean).length})

{task.hardViolations.filter(v => checkedViolations[v.id]).map(v => (
• {v.type}: {v.content}
))} {Object.values(checkedViolations).filter(Boolean).length === 0 && (
未选择任何问题
)}