'use client' import { useState, useEffect } from 'react' import { useRouter } from 'next/navigation' import { Check, Loader2, Video, Search, SlidersHorizontal, ChevronDown } from 'lucide-react' import { MobileLayout } from '@/components/layout/MobileLayout' import { DesktopLayout } from '@/components/layout/DesktopLayout' import { cn } from '@/lib/utils' import { api } from '@/lib/api' import type { TaskResponse } from '@/types/task' // 任务状态类型 type TaskStatus = 'pending_script' | 'pending_video' | 'ai_reviewing' | 'agency_reviewing' | 'need_revision' | 'passed' // 模拟任务数据 const seedTasks = [ { id: 'task-001', title: 'XX品牌618推广', platform: '抖音', description: '产品种草视频 · 时长要求 60-90秒', deadline: '2026-02-10', status: 'pending_script' as TaskStatus, currentStep: 1, // 1-已提交, 2-AI审核, 3-代理商审核, 4-品牌终审 }, { id: 'task-002', title: 'YY美妆新品', platform: '小红书', description: '口播测评 · 视频已上传 · 等待AI审核', submitTime: '今天 14:30', status: 'ai_reviewing' as TaskStatus, currentStep: 2, progress: 65, }, { id: 'task-003', title: 'ZZ饮品夏日', platform: '抖音', description: '探店Vlog · 发现2处问题', reviewTime: '昨天 18:20', status: 'need_revision' as TaskStatus, currentStep: 2, issueCount: 2, }, { id: 'task-004', title: 'AA数码新品发布', platform: '抖音', description: '开箱测评 · 已发布', status: 'passed' as TaskStatus, currentStep: 4, }, { id: 'task-005', title: 'BB运动饮料', platform: '抖音', description: '脚本已通过 · 待提交成片', deadline: '2026-02-12', status: 'pending_video' as TaskStatus, currentStep: 1, }, ] type UiTask = typeof seedTasks[number] const taskProfiles = seedTasks.reduce>((acc, task) => { acc[task.id] = task return acc }, {}) const platformLabelMap: Record = { douyin: '抖音', xiaohongshu: '小红书', bilibili: 'B站', kuaishou: '快手', } const getPlatformLabel = (platform?: string) => { if (!platform) return '未知平台' return platformLabelMap[platform] || platform } const deriveTaskStatus = (task: TaskResponse): TaskStatus => { if (!task.has_script) { return 'pending_script' } if (!task.has_video) { return 'pending_video' } if (task.status === 'approved') { return 'passed' } if (task.status === 'rejected' || task.status === 'failed') { return 'need_revision' } if (task.status === 'pending' || task.status === 'processing') { return 'ai_reviewing' } return 'agency_reviewing' } const getCurrentStep = (status: TaskStatus) => { if (status === 'ai_reviewing' || status === 'need_revision') { return 2 } if (status === 'agency_reviewing') { return 3 } if (status === 'passed') { return 4 } return 1 } const getStatusDescription = (status: TaskStatus) => { switch (status) { case 'pending_script': return '待提交脚本' case 'pending_video': return '待提交视频' case 'ai_reviewing': return 'AI 审核中' case 'agency_reviewing': return '待代理商审核' case 'need_revision': return '需修改后再提交' case 'passed': return '审核通过' default: return '任务进行中' } } const mapApiTaskToUi = (task: TaskResponse): UiTask => { const profile = taskProfiles[task.task_id] const status = deriveTaskStatus(task) const platformLabel = getPlatformLabel(task.platform) const description = profile?.description || `${platformLabel} · ${getStatusDescription(status)}` return { id: task.task_id, title: profile?.title || `任务 ${task.task_id}`, platform: platformLabel, description, deadline: profile?.deadline, submitTime: profile?.submitTime, reviewTime: profile?.reviewTime, status, currentStep: profile?.currentStep || getCurrentStep(status), progress: profile?.progress, issueCount: profile?.issueCount, } } // 状态徽章配置 function getStatusConfig(status: TaskStatus) { switch (status) { case 'pending_script': return { label: '待上传', bg: 'bg-accent-blue/15', text: 'text-accent-blue' } case 'pending_video': return { label: '待上传', bg: 'bg-accent-blue/15', text: 'text-accent-blue' } case 'ai_reviewing': return { label: '审核中', bg: 'bg-accent-indigo/15', text: 'text-accent-indigo' } case 'agency_reviewing': return { label: '审核中', bg: 'bg-accent-amber/15', text: 'text-accent-amber' } case 'need_revision': return { label: '需修改', bg: 'bg-accent-coral/15', text: 'text-accent-coral' } case 'passed': return { label: '已通过', bg: 'bg-accent-green/15', text: 'text-accent-green' } default: return { label: '未知', bg: 'bg-bg-elevated', text: 'text-text-secondary' } } } type StepState = 'done' | 'current' | 'pending' | 'error' function getStepTimeline(status: TaskStatus): Array<{ label: string; state: StepState }> { switch (status) { case 'pending_script': case 'pending_video': return [ { label: '待提交', state: 'current' }, { label: 'AI审核', state: 'pending' }, { label: '代理商', state: 'pending' }, { label: '终审', state: 'pending' }, ] case 'ai_reviewing': return [ { label: '已提交', state: 'done' }, { label: 'AI审核', state: 'current' }, { label: '代理商', state: 'pending' }, { label: '终审', state: 'pending' }, ] case 'need_revision': return [ { label: '已提交', state: 'done' }, { label: 'AI未通过', state: 'error' }, { label: '代理商', state: 'pending' }, { label: '终审', state: 'pending' }, ] case 'agency_reviewing': return [ { label: '已提交', state: 'done' }, { label: 'AI通过', state: 'done' }, { label: '代理商审核', state: 'current' }, { label: '终审', state: 'pending' }, ] case 'passed': return [ { label: '已提交', state: 'done' }, { label: 'AI通过', state: 'done' }, { label: '代理商通过', state: 'done' }, { label: '已通过', state: 'done' }, ] default: return [ { label: '已提交', state: 'pending' }, { label: 'AI审核', state: 'pending' }, { label: '代理商', state: 'pending' }, { label: '终审', state: 'pending' }, ] } } function TaskStepSummary({ status }: { status: TaskStatus }) { const steps = getStepTimeline(status) const stateStyle = (state: StepState) => { if (state === 'done') return 'bg-accent-green text-text-secondary' if (state === 'current') return 'bg-accent-indigo text-accent-indigo' if (state === 'error') return 'bg-accent-coral text-accent-coral' return 'bg-border-subtle text-text-tertiary' } return (
{steps.map((step, index) => (
{step.label} {index < steps.length - 1 && ·}
))}
) } // 审核进度条组件 function ReviewProgressBar({ currentStep, status }: { currentStep: number; status: TaskStatus }) { const steps = [ { label: '已提交', step: 1 }, { label: 'AI审核', step: 2 }, { label: '代理商审核', step: 3 }, { label: '品牌终审', step: 4 }, ] return (
{steps.map((s, index) => { const isCompleted = s.step < currentStep || (s.step === currentStep && status === 'passed') const isCurrent = s.step === currentStep && status !== 'passed' const isError = isCurrent && status === 'need_revision' return (
{isCompleted && } {isCurrent && !isError && } {isError && }
{s.label}
{index < steps.length - 1 && (
)}
) })}
) } // 桌面端任务卡片 function DesktopTaskCard({ task, onClick }: { task: UiTask; onClick: () => void }) { const config = getStatusConfig(task.status) const showProgress = ['ai_reviewing', 'agency_reviewing', 'need_revision'].includes(task.status) const getActionButton = () => { if (task.status === 'pending_script' || task.status === 'pending_video') { return ( ) } if (task.status === 'ai_reviewing') { return ( ) } if (task.status === 'need_revision') { return ( ) } return ( ) } return (
{/* 任务主行 */}
{/* 左侧:缩略图 + 信息 */}
{/* 缩略图占位 */}
{/* 任务信息 */}
{task.title} {task.description}
{/* 右侧:状态 + 操作按钮 */}
{config.label} {getActionButton()}
{/* 审核进度条 */} {showProgress && }
) } // 移动端任务卡片 function MobileTaskCard({ task, onClick }: { task: UiTask; onClick: () => void }) { const config = getStatusConfig(task.status) const showProgress = ['ai_reviewing', 'agency_reviewing', 'need_revision'].includes(task.status) return (
{/* 头部 */}
{task.title} {config.label}
{/* 进度条 */} {showProgress && (
)} {/* 描述 */}

{task.description}

{/* 底部 */}
{task.deadline && `截止: ${task.deadline}`} {task.submitTime && `提交于: ${task.submitTime}`} {task.reviewTime && `审核于: ${task.reviewTime}`} {(task.status === 'pending_script' || task.status === 'pending_video') && ( )} {task.status === 'need_revision' && ( )}
) } export default function CreatorTasksPage() { const router = useRouter() const [isMobile, setIsMobile] = useState(true) const [searchQuery, setSearchQuery] = useState('') const [tasks, setTasks] = useState(seedTasks) const [isLoading, setIsLoading] = useState(false) useEffect(() => { const checkMobile = () => setIsMobile(window.innerWidth < 1024) checkMobile() window.addEventListener('resize', checkMobile) return () => window.removeEventListener('resize', checkMobile) }, []) useEffect(() => { let isMounted = true const fetchTasks = async () => { setIsLoading(true) try { const data = await api.listTasks() if (!isMounted) return const mapped = data.items.map(mapApiTaskToUi) setTasks(mapped) } catch (error) { console.error('加载任务失败:', error) } finally { if (isMounted) { setIsLoading(false) } } } fetchTasks() return () => { isMounted = false } }, []) const pendingCount = tasks.filter(t => !['passed'].includes(t.status) ).length const handleTaskClick = (taskId: string) => { router.push(`/creator/task/${taskId}`) } // 桌面端内容 const DesktopContent = (
{/* 顶部栏 */}
{/* 页面标题 */}

我的任务

共 {pendingCount} 个进行中任务

{/* 搜索和筛选 */}
setSearchQuery(e.target.value)} className="bg-transparent text-sm text-text-primary placeholder-text-tertiary focus:outline-none w-32" />
{/* 任务列表 */}
{isLoading && (
正在加载任务...
)} {!isLoading && tasks.length === 0 && (
暂无任务
)} {tasks.map((task) => ( handleTaskClick(task.id)} /> ))}
) // 移动端内容 const MobileContent = (
{/* 头部 */}

我的任务

共 {pendingCount} 个进行中任务

{/* 任务列表 */}
{isLoading && (
正在加载任务...
)} {!isLoading && tasks.length === 0 && (
暂无任务
)} {tasks.map((task) => ( handleTaskClick(task.id)} /> ))}
) return isMobile ? MobileContent : DesktopContent }