feat(creator): 完成达人端前端页面开发
- 新增申诉中心页面(列表、详情、新建申诉) - 新增申诉次数管理页面(按任务显示配额,支持向代理商申请) - 新增个人中心页面(达人ID复制、菜单导航) - 新增个人信息编辑、账户设置、消息通知设置页面 - 新增帮助中心和历史记录页面 - 新增脚本提交和视频提交页面 - 优化消息中心页面(消息详情跳转) - 优化任务详情页面布局和交互 - 更新 ResponsiveLayout、Sidebar、ReviewSteps 通用组件 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
1011e73643
commit
2f9b7f05fd
@@ -0,0 +1,203 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import {
|
||||
ArrowLeft,
|
||||
CheckCircle,
|
||||
XCircle,
|
||||
Clock,
|
||||
Video,
|
||||
Filter,
|
||||
ChevronRight
|
||||
} from 'lucide-react'
|
||||
import { ResponsiveLayout } from '@/components/layout/ResponsiveLayout'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
// 历史任务状态类型
|
||||
type HistoryStatus = 'completed' | 'expired' | 'cancelled'
|
||||
|
||||
// 历史任务数据类型
|
||||
type HistoryTask = {
|
||||
id: string
|
||||
title: string
|
||||
description: string
|
||||
status: HistoryStatus
|
||||
completedAt?: string
|
||||
expiredAt?: string
|
||||
platform: string
|
||||
}
|
||||
|
||||
// 模拟历史数据
|
||||
const mockHistory: HistoryTask[] = [
|
||||
{
|
||||
id: 'hist-001',
|
||||
title: 'MM春季护肤品推广',
|
||||
description: '产品测评 · 已发布',
|
||||
status: 'completed',
|
||||
completedAt: '2026-01-20',
|
||||
platform: '抖音',
|
||||
},
|
||||
{
|
||||
id: 'hist-002',
|
||||
title: 'NN零食新品试吃',
|
||||
description: '美食测评 · 已发布',
|
||||
status: 'completed',
|
||||
completedAt: '2026-01-15',
|
||||
platform: '小红书',
|
||||
},
|
||||
{
|
||||
id: 'hist-003',
|
||||
title: 'OO运动装备测评',
|
||||
description: '运动视频 · 已过期',
|
||||
status: 'expired',
|
||||
expiredAt: '2026-01-10',
|
||||
platform: '抖音',
|
||||
},
|
||||
{
|
||||
id: 'hist-004',
|
||||
title: 'PP家居用品展示',
|
||||
description: '生活vlog · 已取消',
|
||||
status: 'cancelled',
|
||||
expiredAt: '2026-01-05',
|
||||
platform: 'B站',
|
||||
},
|
||||
{
|
||||
id: 'hist-005',
|
||||
title: 'QQ电子产品开箱',
|
||||
description: '科技测评 · 已发布',
|
||||
status: 'completed',
|
||||
completedAt: '2025-12-28',
|
||||
platform: '抖音',
|
||||
},
|
||||
{
|
||||
id: 'hist-006',
|
||||
title: 'RR母婴用品推荐',
|
||||
description: '种草视频 · 已发布',
|
||||
status: 'completed',
|
||||
completedAt: '2025-12-20',
|
||||
platform: '小红书',
|
||||
},
|
||||
]
|
||||
|
||||
// 状态配置
|
||||
const statusConfig: Record<HistoryStatus, { label: string; color: string; bgColor: string; icon: React.ElementType }> = {
|
||||
completed: { label: '已完成', color: 'text-accent-green', bgColor: 'bg-accent-green/15', icon: CheckCircle },
|
||||
expired: { label: '已过期', color: 'text-text-tertiary', bgColor: 'bg-bg-elevated', icon: Clock },
|
||||
cancelled: { label: '已取消', color: 'text-accent-coral', bgColor: 'bg-accent-coral/15', icon: XCircle },
|
||||
}
|
||||
|
||||
// 历史任务卡片
|
||||
function HistoryCard({ task, onClick }: { task: HistoryTask; onClick: () => void }) {
|
||||
const status = statusConfig[task.status]
|
||||
const StatusIcon = status.icon
|
||||
|
||||
return (
|
||||
<div
|
||||
className="bg-bg-card rounded-2xl p-5 card-shadow cursor-pointer hover:bg-bg-elevated/30 transition-colors"
|
||||
onClick={onClick}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-16 h-12 rounded-lg bg-[#1A1A1E] flex items-center justify-center flex-shrink-0">
|
||||
<Video className="w-5 h-5 text-text-tertiary" />
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-base font-semibold text-text-primary">{task.title}</span>
|
||||
<span className="text-sm text-text-secondary">{task.description}</span>
|
||||
<div className="flex items-center gap-3 mt-1">
|
||||
<span className="text-xs text-text-tertiary">{task.platform}</span>
|
||||
<span className="text-xs text-text-tertiary">
|
||||
{task.completedAt || task.expiredAt}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={cn('px-3 py-1.5 rounded-lg flex items-center gap-1.5', status.bgColor)}>
|
||||
<StatusIcon className={cn('w-4 h-4', status.color)} />
|
||||
<span className={cn('text-sm font-medium', status.color)}>{status.label}</span>
|
||||
</div>
|
||||
<ChevronRight className="w-5 h-5 text-text-tertiary" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function CreatorHistoryPage() {
|
||||
const router = useRouter()
|
||||
const [filter, setFilter] = useState<HistoryStatus | 'all'>('all')
|
||||
|
||||
const filteredHistory = filter === 'all' ? mockHistory : mockHistory.filter(t => t.status === filter)
|
||||
|
||||
return (
|
||||
<ResponsiveLayout role="creator">
|
||||
<div className="flex flex-col gap-6 h-full">
|
||||
{/* 顶部栏 */}
|
||||
<div className="flex items-center justify-between flex-wrap gap-4">
|
||||
<div className="flex flex-col gap-1">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => router.back()}
|
||||
className="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-bg-elevated text-text-secondary text-sm hover:bg-bg-card transition-colors w-fit mb-2"
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4" />
|
||||
返回
|
||||
</button>
|
||||
<h1 className="text-xl lg:text-[28px] font-bold text-text-primary">历史记录</h1>
|
||||
<p className="text-sm lg:text-[15px] text-text-secondary">查看已完成和过期的任务</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 px-4 py-2.5 bg-bg-card rounded-xl border border-border-subtle">
|
||||
<Filter className="w-[18px] h-[18px] text-text-secondary" />
|
||||
<select
|
||||
value={filter}
|
||||
onChange={(e) => setFilter(e.target.value as HistoryStatus | 'all')}
|
||||
className="bg-transparent text-sm text-text-primary focus:outline-none"
|
||||
>
|
||||
<option value="all">全部状态</option>
|
||||
<option value="completed">已完成</option>
|
||||
<option value="expired">已过期</option>
|
||||
<option value="cancelled">已取消</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 统计信息 */}
|
||||
<div className="flex items-center gap-6 bg-bg-card rounded-2xl p-5 card-shadow">
|
||||
<div className="flex flex-col items-center gap-1 flex-1">
|
||||
<span className="text-2xl font-bold text-accent-green">
|
||||
{mockHistory.filter(t => t.status === 'completed').length}
|
||||
</span>
|
||||
<span className="text-xs text-text-tertiary">已完成</span>
|
||||
</div>
|
||||
<div className="w-px h-10 bg-border-subtle" />
|
||||
<div className="flex flex-col items-center gap-1 flex-1">
|
||||
<span className="text-2xl font-bold text-text-tertiary">
|
||||
{mockHistory.filter(t => t.status === 'expired').length}
|
||||
</span>
|
||||
<span className="text-xs text-text-tertiary">已过期</span>
|
||||
</div>
|
||||
<div className="w-px h-10 bg-border-subtle" />
|
||||
<div className="flex flex-col items-center gap-1 flex-1">
|
||||
<span className="text-2xl font-bold text-accent-coral">
|
||||
{mockHistory.filter(t => t.status === 'cancelled').length}
|
||||
</span>
|
||||
<span className="text-xs text-text-tertiary">已取消</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 任务列表 */}
|
||||
<div className="flex flex-col gap-4 flex-1 overflow-y-auto pr-2">
|
||||
{filteredHistory.map((task) => (
|
||||
<HistoryCard
|
||||
key={task.id}
|
||||
task={task}
|
||||
onClick={() => router.push(`/creator/task/${task.id}`)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</ResponsiveLayout>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user