'use client' import { useState } from 'react' import { useRouter } from 'next/navigation' 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 { Bell, CheckCircle, XCircle, AlertTriangle, FileText, Video, Users, Clock, Check, MoreVertical, PlusCircle, UserCheck, UserX, Bot, Settings, CalendarClock, Building2, Eye } from 'lucide-react' import { getPlatformInfo } from '@/lib/platforms' import { cn } from '@/lib/utils' // 消息类型 type MessageType = | 'appeal_quota_request' // 达人申请增加申诉次数 | 'task_submitted' // 达人提交了脚本/视频 | 'review_complete' // 品牌终审通过 | 'review_rejected' // 品牌终审驳回 | 'new_project' // 被品牌邀请参与项目 | 'warning' // 风险预警 | 'creator_accept' // 达人接受签约邀请 | 'creator_reject' // 达人拒绝签约邀请 | 'ai_review_complete' // AI审核完成,待代理商审核 | 'brand_config_updated' // 品牌方更新了配置 | 'task_deadline' // 任务截止提醒 | 'brand_brief_updated' // 品牌方更新了Brief | 'system_notice' // 系统通知 interface Message { id: string type: MessageType title: string content: string time: string read: boolean icon: typeof Bell iconColor: string bgColor: string platform?: string taskId?: string projectId?: string creatorName?: string hasAction?: boolean actionType?: 'review' | 'view' | 'config' // 申诉次数请求专用字段 appealRequest?: { creatorName: string taskName: string taskId: string status: 'pending' | 'approved' | 'rejected' } } // 模拟消息列表 const mockMessages: Message[] = [ { id: 'msg-001', type: 'appeal_quota_request', title: '申诉次数申请', content: '达人「李小红」申请增加「618美妆推广视频」的申诉次数', time: '5分钟前', read: false, icon: PlusCircle, iconColor: 'text-accent-amber', bgColor: 'bg-accent-amber/20', platform: 'douyin', appealRequest: { creatorName: '李小红', taskName: '618美妆推广视频', taskId: 'task-001', status: 'pending', }, }, { id: 'msg-002', type: 'ai_review_complete', title: 'AI审核完成', content: '达人「小美护肤」的脚本【夏日护肤推广】已通过AI审核,请及时进行人工审核', time: '10分钟前', read: false, icon: Bot, iconColor: 'text-accent-indigo', bgColor: 'bg-accent-indigo/20', platform: 'xiaohongshu', taskId: 'task-006', hasAction: true, actionType: 'review', }, { id: 'msg-003', type: 'creator_accept', title: '达人已签约', content: '达人「美妆达人小王」已接受您的签约邀请,可以开始分配任务', time: '20分钟前', read: false, icon: UserCheck, iconColor: 'text-accent-green', bgColor: 'bg-accent-green/20', creatorName: '美妆达人小王', }, { id: 'msg-004', type: 'task_submitted', title: '新脚本提交', content: '达人「小美护肤」提交了「夏日护肤推广脚本」,请及时审核', time: '30分钟前', read: false, icon: FileText, iconColor: 'text-accent-indigo', bgColor: 'bg-accent-indigo/20', platform: 'xiaohongshu', taskId: 'task-006', hasAction: true, actionType: 'review', }, { id: 'msg-005', type: 'appeal_quota_request', title: '申诉次数申请', content: '达人「美妆达人小王」申请增加「双11护肤品种草」的申诉次数', time: '30分钟前', read: false, icon: PlusCircle, iconColor: 'text-accent-amber', bgColor: 'bg-accent-amber/20', platform: 'xiaohongshu', appealRequest: { creatorName: '美妆达人小王', taskName: '双11护肤品种草', taskId: 'task-002', status: 'pending', }, }, { id: 'msg-006', type: 'task_deadline', title: '任务即将截止', content: '【XX品牌618推广】任务将于3天后截止,还有5位达人未提交脚本', time: '1小时前', read: false, icon: CalendarClock, iconColor: 'text-orange-400', bgColor: 'bg-orange-500/20', platform: 'douyin', hasAction: true, actionType: 'view', }, { id: 'msg-007', type: 'review_complete', title: '品牌终审通过', content: '【XX品牌618推广】达人「美妆小红」的视频「新品口红试色」已通过品牌方终审,可通知达人发布', time: '1小时前', read: false, icon: CheckCircle, iconColor: 'text-accent-green', bgColor: 'bg-accent-green/20', platform: 'xiaohongshu', taskId: 'task-004', }, { id: 'msg-008', type: 'review_rejected', title: '品牌终审驳回', content: '【BB运动饮料】达人「健身教练王」的视频「健身器材开箱」被品牌方驳回,原因:违禁词使用,请通知达人修改', time: '2小时前', read: false, icon: XCircle, iconColor: 'text-accent-coral', bgColor: 'bg-accent-coral/20', platform: 'bilibili', taskId: 'task-010', }, { id: 'msg-009', type: 'brand_config_updated', title: '品牌规则更新', content: '品牌方「XX护肤品牌」更新了违禁词配置,新增8个违禁词', time: '3小时前', read: true, icon: Settings, iconColor: 'text-accent-amber', bgColor: 'bg-accent-amber/20', hasAction: true, actionType: 'config', }, { id: 'msg-010', type: 'brand_brief_updated', title: 'Brief更新通知', content: '品牌方更新了【XX品牌618推广】的Brief要求,请查看最新内容', time: '4小时前', read: true, icon: FileText, iconColor: 'text-accent-indigo', bgColor: 'bg-accent-indigo/20', projectId: 'proj-001', hasAction: true, actionType: 'view', }, { id: 'msg-011', type: 'creator_reject', title: '达人已拒绝', content: '达人「时尚博主Anna」拒绝了您的签约邀请', time: '昨天 14:30', read: true, icon: UserX, iconColor: 'text-accent-coral', bgColor: 'bg-accent-coral/20', creatorName: '时尚博主Anna', }, { id: 'msg-012', type: 'new_project', title: '新项目邀请', content: '您被邀请参与「XX品牌新品推广」项目,请配置 Brief', time: '昨天', read: true, icon: Building2, iconColor: 'text-purple-400', bgColor: 'bg-purple-500/20', platform: 'douyin', projectId: 'proj-001', hasAction: true, actionType: 'config', }, { id: 'msg-013', type: 'warning', title: '风险预警', content: '达人「美妆Lisa」连续2次提交被驳回,建议关注并提供指导', time: '昨天', read: true, icon: AlertTriangle, iconColor: 'text-orange-400', bgColor: 'bg-orange-500/20', platform: 'xiaohongshu', creatorName: '美妆Lisa', }, { id: 'msg-015', type: 'task_submitted', title: '新视频提交', content: '达人「健身教练王」提交了「健身器材使用教程」视频,请及时审核', time: '2天前', read: true, icon: Video, iconColor: 'text-purple-400', bgColor: 'bg-purple-500/20', platform: 'bilibili', taskId: 'task-009', hasAction: true, actionType: 'review', }, { id: 'msg-016', type: 'system_notice', title: '系统通知', content: '平台违禁词库已更新,「抖音」平台新增美妆类目违禁词56个', time: '3天前', read: true, icon: Bell, iconColor: 'text-text-secondary', bgColor: 'bg-bg-elevated', }, ] export default function AgencyMessagesPage() { const router = useRouter() const [messages, setMessages] = useState(mockMessages) const [filter, setFilter] = useState<'all' | 'unread' | 'pending'>('all') const unreadCount = messages.filter(m => !m.read).length const pendingAppealRequests = messages.filter(m => m.appealRequest?.status === 'pending').length const pendingReviewCount = messages.filter(m => !m.read && (m.type === 'task_submitted' || m.type === 'ai_review_complete') ).length const getFilteredMessages = () => { switch (filter) { case 'unread': return messages.filter(m => !m.read) case 'pending': return messages.filter(m => m.type === 'task_submitted' || m.type === 'ai_review_complete' || m.type === 'appeal_quota_request' ) default: return messages } } const filteredMessages = getFilteredMessages() const markAsRead = (id: string) => { setMessages(prev => prev.map(m => m.id === id ? { ...m, read: true } : m)) } const markAllAsRead = () => { setMessages(prev => prev.map(m => ({ ...m, read: true }))) } // 处理申诉次数请求 const handleAppealRequest = (messageId: string, action: 'approve' | 'reject') => { setMessages(prev => prev.map(m => { if (m.id === messageId && m.appealRequest) { return { ...m, read: true, appealRequest: { ...m.appealRequest, status: action === 'approve' ? 'approved' : 'rejected', }, } } return m })) } // 处理消息点击 const handleMessageClick = (message: Message) => { if (message.type === 'appeal_quota_request') return // 申诉请求不跳转 if (message.type === 'system_notice') return // 系统通知不跳转 markAsRead(message.id) // 根据消息类型决定跳转 switch (message.type) { case 'creator_accept': case 'creator_reject': // 达人签约相关 -> 达人管理 router.push('/agency/creators') break case 'warning': // 风险预警 -> 达人管理 router.push('/agency/creators') break case 'brand_config_updated': // 品牌规则更新 -> Brief配置 router.push('/agency/briefs') break case 'task_deadline': // 任务截止提醒 -> 任务列表 if (message.projectId) { router.push(`/agency/briefs/${message.projectId}`) } else { router.push('/agency/review') } break default: // 默认逻辑 if (message.taskId) { router.push(`/agency/review/${message.taskId}`) } else if (message.projectId) { router.push(`/agency/briefs/${message.projectId}`) } } } // 处理操作按钮点击 const handleAction = (message: Message, e: React.MouseEvent) => { e.stopPropagation() markAsRead(message.id) switch (message.actionType) { case 'review': if (message.taskId) { router.push(`/agency/review/${message.taskId}`) } else { router.push('/agency/review') } break case 'view': if (message.projectId) { router.push(`/agency/briefs/${message.projectId}`) } else if (message.type === 'task_deadline') { router.push('/agency/review') } else { router.push('/agency/creators') } break case 'config': if (message.projectId) { router.push(`/agency/briefs/${message.projectId}`) } else { router.push('/agency/briefs') } break } } return (
{message.content}
{filter === 'unread' ? '没有未读消息' : '暂无消息'}