import { useEffect, useState } from 'react'; import { Table, Button, Card, Row, Col, Statistic, message, Tag, Popconfirm, Space, Typography, Input, theme, Dropdown } from 'antd'; import { DownloadOutlined, DeleteOutlined, CopyOutlined, SearchOutlined } from '@ant-design/icons'; import { cookieApi } from '../api/modules'; import { getUser, hasPerm } from '../store/auth'; import { formatTime } from '../utils/time'; const { Text } = Typography; export default function CookiePage() { const { token } = theme.useToken(); const [cookies, setCookies] = useState([]); const [loading, setLoading] = useState(false); const [selectedRowKeys, setSelectedRowKeys] = useState([]); const [searchText, setSearchText] = useState(''); const user = getUser(); const canView = hasPerm(user, 'cookie:view'); const canExport = hasPerm(user, 'cookie:export'); const loadCookies = async () => { setLoading(true); try { const data = await cookieApi.list(); setCookies(data); } catch (e: any) { message.error(e.message); } finally { setLoading(false); } }; useEffect(() => { loadCookies(); }, []); const handleExport = async (format: string = 'csv') => { try { const blob = await cookieApi.exportCsv(format); const url = URL.createObjectURL(blob instanceof Blob ? blob : new Blob([blob as any])); const a = document.createElement('a'); a.href = url; a.download = format === 'custom' ? 'cookies_custom.txt' : 'cookies.csv'; a.click(); URL.revokeObjectURL(url); message.success('已导出'); } catch (e: any) { message.error(e.message); } }; const handleCopyCookie = (cookie: string, username: string) => { if (!cookie) { message.warning('Cookie 为空'); return; } navigator.clipboard.writeText(cookie).then(() => { message.success(`已复制 ${username} 的 Cookie`); }).catch(() => { message.error('复制失败'); }); }; const handleCopySelected = () => { if (selectedRowKeys.length === 0) { message.warning('请先选择 Cookie'); return; } const selected = cookies.filter((c) => selectedRowKeys.includes(c.id)); const text = selected .map((c) => `${c.account_username}: ${c.cookie || '(空)'}`) .join('\n'); navigator.clipboard.writeText(text).then(() => { message.success(`已复制 ${selected.length} 条 Cookie`); }).catch(() => { message.error('复制失败'); }); }; const handleDelete = async (id: number) => { try { await cookieApi.delete(id); message.success('已删除'); setSelectedRowKeys((prev) => prev.filter((k) => k !== id)); loadCookies(); } catch (e: any) { message.error(e.message); } }; // 筛选 const filteredCookies = cookies.filter((c) => { if (!searchText) return true; const s = searchText.toLowerCase(); return ( c.account_username?.toLowerCase().includes(s) || c.assigned_username?.toLowerCase().includes(s) ); }); const columns: any[] = [ { title: 'ID', dataIndex: 'id', width: 60, align: 'center' }, { title: '账号', dataIndex: 'account_username', width: 140, ellipsis: true, }, { title: '分配', dataIndex: 'assigned_username', width: 100, align: 'center', render: (name: string | null) => name ? {name} : 未分配, }, { title: 'Cookie', dataIndex: 'cookie_preview', ellipsis: true, render: (val: string) => { if (!canView) return ***; return {val}; }, }, { title: '时间', dataIndex: 'created_at', width: 180, align: 'center', render: (val: string) => formatTime(val), }, { title: '操作', width: 130, align: 'center', fixed: 'right', render: (_: any, record: any) => ( {canExport && ( handleDelete(record.id)}> {canExport && ( handleExport('csv') }, { key: 'custom', label: '自定义(账号----密码----ck)', onClick: () => handleExport('custom') }, ], }} > )}
setSearchText(e.target.value)} style={{ width: 260 }} size="small" prefix={} />
setSelectedRowKeys(keys), }} columns={columns} dataSource={filteredCookies} rowKey="id" loading={loading} size="small" pagination={{ pageSize: 20, showSizeChanger: true, showTotal: (t) => `共 ${t} 条` }} scroll={{ x: 900 }} /> ); }