'use client' import { useState, useEffect, useCallback } from 'react' import { useRouter } from 'next/navigation' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card' import { Button } from '@/components/ui/Button' import { ArrowLeft, History, CheckCircle, XCircle, Search, Filter, FileText, Video, User, Calendar, Download, Loader2 } from 'lucide-react' import { api } from '@/lib/api' import { USE_MOCK } from '@/contexts/AuthContext' import type { TaskResponse } from '@/types/task' // 审核历史记录类型 interface ReviewHistoryItem { id: string taskId: string taskTitle: string creatorName: string contentType: 'script' | 'video' result: 'approved' | 'rejected' reason?: string reviewedAt: string projectName: string } // 模拟审核历史数据 const mockHistoryData: ReviewHistoryItem[] = [ { id: 'h-001', taskId: 'task-101', taskTitle: '夏日护肤推广脚本', creatorName: '小美护肤', contentType: 'script', result: 'approved', reviewedAt: '2026-02-06 14:30', projectName: 'XX品牌618推广', }, { id: 'h-002', taskId: 'task-102', taskTitle: '新品口红试色视频', creatorName: '美妆Lisa', contentType: 'video', result: 'rejected', reason: '背景音乐版权问题', reviewedAt: '2026-02-06 11:20', projectName: 'YY口红新品发布', }, { id: 'h-003', taskId: 'task-103', taskTitle: '健身器材推荐脚本', creatorName: '健身教练王', contentType: 'script', result: 'approved', reviewedAt: '2026-02-05 16:45', projectName: 'ZZ运动品牌推广', }, { id: 'h-004', taskId: 'task-104', taskTitle: '美妆新品测评视频', creatorName: '达人小红', contentType: 'video', result: 'rejected', reason: '品牌调性不符', reviewedAt: '2026-02-05 10:15', projectName: 'XX品牌618推广', }, { id: 'h-005', taskId: 'task-105', taskTitle: '数码产品开箱脚本', creatorName: '科技小哥', contentType: 'script', result: 'approved', reviewedAt: '2026-02-04 15:30', projectName: 'AA数码新品上市', }, ] /** * Map a completed TaskResponse to the ReviewHistoryItem UI model. */ function mapTaskToHistoryItem(task: TaskResponse): ReviewHistoryItem { // Determine content type based on the latest stage info // If the task reached video stages, it's a video review; otherwise script const hasVideoReview = task.video_agency_status !== null && task.video_agency_status !== undefined const contentType: 'script' | 'video' = hasVideoReview ? 'video' : 'script' // Determine result let result: 'approved' | 'rejected' = 'approved' let reason: string | undefined if (task.stage === 'rejected') { result = 'rejected' // Try to pick up the rejection reason if (hasVideoReview) { reason = task.video_agency_comment || task.video_brand_comment || undefined } else { reason = task.script_agency_comment || task.script_brand_comment || undefined } } else if (task.stage === 'completed') { result = 'approved' } const formatDate = (dateStr: string) => { return new Date(dateStr).toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', }).replace(/\//g, '-') } return { id: task.id, taskId: task.id, taskTitle: task.name, creatorName: task.creator.name, contentType, result, reason, reviewedAt: formatDate(task.updated_at), projectName: task.project.name, } } export default function AgencyReviewHistoryPage() { const router = useRouter() const [searchQuery, setSearchQuery] = useState('') const [filterResult, setFilterResult] = useState<'all' | 'approved' | 'rejected'>('all') const [filterType, setFilterType] = useState<'all' | 'script' | 'video'>('all') const [historyData, setHistoryData] = useState([]) const [loading, setLoading] = useState(true) const fetchHistory = useCallback(async () => { if (USE_MOCK) { setHistoryData(mockHistoryData) setLoading(false) return } try { setLoading(true) const response = await api.listTasks(1, 50, 'completed') setHistoryData(response.items.map(mapTaskToHistoryItem)) } catch (err) { console.error('Failed to fetch review history:', err) setHistoryData([]) } finally { setLoading(false) } }, []) useEffect(() => { fetchHistory() }, [fetchHistory]) // 筛选数据 const filteredHistory = historyData.filter(item => { const matchesSearch = searchQuery === '' || item.taskTitle.toLowerCase().includes(searchQuery.toLowerCase()) || item.creatorName.toLowerCase().includes(searchQuery.toLowerCase()) || item.projectName.toLowerCase().includes(searchQuery.toLowerCase()) const matchesResult = filterResult === 'all' || item.result === filterResult const matchesType = filterType === 'all' || item.contentType === filterType return matchesSearch && matchesResult && matchesType }) // 统计 const approvedCount = historyData.filter(i => i.result === 'approved').length const rejectedCount = historyData.filter(i => i.result === 'rejected').length return (
{/* 顶部导航 */}

审核历史

查看您的历史审核记录

{/* 统计卡片 */}

{historyData.length}

总审核数

{approvedCount}

已通过

{rejectedCount}

已驳回

{/* 搜索和筛选 */}
setSearchQuery(e.target.value)} className="w-full pl-10 pr-4 py-2.5 border border-border-subtle rounded-xl bg-bg-elevated text-text-primary focus:outline-none focus:ring-2 focus:ring-accent-indigo" />
结果:
{[ { value: 'all', label: '全部' }, { value: 'approved', label: '通过' }, { value: 'rejected', label: '驳回' }, ].map((tab) => ( ))}
类型:
{[ { value: 'all', label: '全部' }, { value: 'script', label: '脚本' }, { value: 'video', label: '视频' }, ].map((tab) => ( ))}
{/* 历史列表 */} 审核记录 共 {filteredHistory.length} 条 {loading ? (

加载中...

) : filteredHistory.length > 0 ? ( filteredHistory.map((item) => (
{item.result === 'approved' ? '已通过' : '已驳回'} {item.contentType === 'script' ? :

{item.taskTitle}

{item.creatorName} {item.projectName}
{item.reason && (

驳回原因: {item.reason}

)}
{item.reviewedAt}
)) ) : (

没有找到匹配的审核记录

)}
) }