import { useCallback, useEffect, useState } from 'react' import { Filter, RefreshCw, Trash2, Upload } from 'lucide-react' import { Button } from '@/components/ui/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card' // import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { ScrollArea } from '@/components/ui/scroll-area' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select' import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog' import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog' import { useToast } from '@/hooks/use-toast' import { banEmoji, batchDeleteEmojis, deleteEmoji, getEmojiList, getEmojiStats, registerEmoji, } from '@/lib/emoji-api' import type { Emoji, EmojiStats } from '@/types/emoji' import { EmojiDetailDialog, EmojiEditDialog, EmojiUploadDialog, } from './EmojiDialogs' import { EmojiList } from './EmojiList' export function EmojiManagementPage() { const [emojiList, setEmojiList] = useState([]) const [stats, setStats] = useState(null) const [loading, setLoading] = useState(false) const [page, setPage] = useState(1) const [total, setTotal] = useState(0) const [pageSize, setPageSize] = useState(20) const [registeredFilter, setRegisteredFilter] = useState('registered') const [bannedFilter, setBannedFilter] = useState('all') const [formatFilter, setFormatFilter] = useState('all') const [sortBy, setSortBy] = useState('usage_count') const [sortOrder, setSortOrder] = useState<'desc' | 'asc'>('desc') const [selectedEmoji, setSelectedEmoji] = useState(null) const [detailDialogOpen, setDetailDialogOpen] = useState(false) const [editDialogOpen, setEditDialogOpen] = useState(false) const [deleteDialogOpen, setDeleteDialogOpen] = useState(false) const [selectedIds, setSelectedIds] = useState>(new Set()) const [batchDeleteDialogOpen, setBatchDeleteDialogOpen] = useState(false) const [jumpToPage, setJumpToPage] = useState('') const [cardSize, setCardSize] = useState<'small' | 'medium' | 'large'>( 'medium' ) const [uploadDialogOpen, setUploadDialogOpen] = useState(false) const { toast } = useToast() // 加载表情包列表 const loadEmojiList = useCallback(async () => { try { setLoading(true) const response = await getEmojiList({ page, page_size: pageSize, is_registered: registeredFilter === 'all' ? undefined : registeredFilter === 'registered', is_banned: bannedFilter === 'all' ? undefined : bannedFilter === 'banned', format: formatFilter === 'all' ? undefined : formatFilter, sort_by: sortBy, sort_order: sortOrder, }) setEmojiList(response.data) setTotal(response.total) } catch (error) { const message = error instanceof Error ? error.message : '加载表情包列表失败' toast({ title: '错误', description: message, variant: 'destructive', }) } finally { setLoading(false) } }, [ page, pageSize, registeredFilter, bannedFilter, formatFilter, sortBy, sortOrder, toast, ]) // 加载统计数据 const loadStats = async () => { try { const response = await getEmojiStats() setStats(response.data) } catch (error) { console.error('加载统计数据失败:', error) } } useEffect(() => { loadEmojiList() }, [loadEmojiList]) useEffect(() => { loadStats() }, []) // 查看详情 const handleViewDetail = async (emoji: Emoji) => { setSelectedEmoji(emoji) setDetailDialogOpen(true) } // 编辑表情包 const handleEdit = (emoji: Emoji) => { setSelectedEmoji(emoji) setEditDialogOpen(true) } // 删除表情包 const handleDelete = (emoji: Emoji) => { setSelectedEmoji(emoji) setDeleteDialogOpen(true) } // 确认删除 const confirmDelete = async () => { if (!selectedEmoji) return try { await deleteEmoji(selectedEmoji.id) toast({ title: '成功', description: '表情包已删除', }) setDeleteDialogOpen(false) setSelectedEmoji(null) loadEmojiList() loadStats() } catch (error) { const message = error instanceof Error ? error.message : '删除失败' toast({ title: '错误', description: message, variant: 'destructive', }) } } // 快速注册 const handleRegister = async (emoji: Emoji) => { try { await registerEmoji(emoji.id) toast({ title: '成功', description: '表情包已注册', }) loadEmojiList() loadStats() } catch (error) { const message = error instanceof Error ? error.message : '注册失败' toast({ title: '错误', description: message, variant: 'destructive', }) } } // 快速封禁 const handleBan = async (emoji: Emoji) => { try { await banEmoji(emoji.id) toast({ title: '成功', description: '表情包已封禁', }) loadEmojiList() loadStats() } catch (error) { const message = error instanceof Error ? error.message : '封禁失败' toast({ title: '错误', description: message, variant: 'destructive', }) } } // 切换选择 const toggleSelect = (id: number) => { const newSelected = new Set(selectedIds) if (newSelected.has(id)) { newSelected.delete(id) } else { newSelected.add(id) } setSelectedIds(newSelected) } // 批量删除 const handleBatchDelete = async () => { try { const result = await batchDeleteEmojis(Array.from(selectedIds)) toast({ title: '批量删除完成', description: result.message, }) setSelectedIds(new Set()) setBatchDeleteDialogOpen(false) loadEmojiList() loadStats() } catch (error) { toast({ title: '批量删除失败', description: error instanceof Error ? error.message : '批量删除失败', variant: 'destructive', }) } } // 页面跳转 const handleJumpToPage = () => { const targetPage = parseInt(jumpToPage) const totalPages = Math.ceil(total / pageSize) if (targetPage >= 1 && targetPage <= totalPages) { setPage(targetPage) setJumpToPage('') } else { toast({ title: '无效的页码', description: `请输入1-${totalPages}之间的页码`, variant: 'destructive', }) } } // 获取格式选项 const formatOptions = stats?.formats ? Object.keys(stats.formats) : [] return (
{/* 页面标题 */}

表情包

管理麦麦的表情包资源

{/* 统计卡片 */} {stats && (
总数 {stats.total} 已注册 {stats.registered} 已封禁 {stats.banned} 未注册 {stats.unregistered}
)} {/* 筛选和排序 */} 筛选和排序
{selectedIds.size > 0 && ( 已选择 {selectedIds.size} 个表情包 )} {/* 卡片尺寸切换 */}
{selectedIds.size > 0 && ( <> )}
{/* 表情包卡片列表 */} 表情包列表 共 {total} 个表情包,当前第 {page} 页 {/* 详情对话框 */} {/* 编辑对话框 */} { loadEmojiList() loadStats() }} /> {/* 上传对话框 */} { loadEmojiList() loadStats() }} />
{/* 批量删除确认对话框 */} 确认批量删除 你确定要删除选中的 {selectedIds.size}{' '} 个表情包吗?此操作不可撤销。 取消 确认删除 {/* 删除确认对话框 */} 确认删除 确定要删除这个表情包吗?此操作无法撤销。
) }