优化退出登录, cookie 可以复制

This commit is contained in:
yml2213
2026-06-22 14:54:32 +08:00
parent 627f06d0a0
commit 5fa91c1bb4
2 changed files with 149 additions and 75 deletions
+68 -17
View File
@@ -1,12 +1,13 @@
import { useEffect, useState } from 'react';
import { Table, Button, Card, Row, Col, Statistic, message, Tag, Popconfirm } from 'antd';
import { DownloadOutlined, DeleteOutlined } from '@ant-design/icons';
import { Table, Button, Card, Row, Col, Statistic, message, Tag, Popconfirm, Space } from 'antd';
import { DownloadOutlined, DeleteOutlined, CopyOutlined } from '@ant-design/icons';
import { cookieApi } from '../api/modules';
import { getUser, hasPerm } from '../store/auth';
export default function CookiePage() {
const [cookies, setCookies] = useState<any[]>([]);
const [loading, setLoading] = useState(false);
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const user = getUser();
const canView = hasPerm(user, 'cookie:view');
@@ -43,10 +44,39 @@ export default function CookiePage() {
}
};
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);
@@ -65,30 +95,47 @@ export default function CookiePage() {
return <span style={{ fontFamily: 'monospace', fontSize: 12 }}>{val}</span>;
},
},
{ title: '时间', dataIndex: 'created_at', width: 180 },
];
if (canExport) {
columns.push({
{ title: '时间', dataIndex: 'created_at', width: 170 },
{
title: '操作',
width: 80,
width: 160,
render: (_: any, record: any) => (
<Popconfirm title="确认删除?" onConfirm={() => handleDelete(record.id)}>
<Button danger size="small" icon={<DeleteOutlined />}></Button>
</Popconfirm>
<Space size={4}>
<Button
size="small"
icon={<CopyOutlined />}
onClick={() => handleCopyCookie(record.cookie, record.account_username)}
>
</Button>
{canExport && (
<Popconfirm title="确认删除?" onConfirm={() => handleDelete(record.id)}>
<Button danger size="small" icon={<DeleteOutlined />} />
</Popconfirm>
)}
</Space>
),
});
}
},
];
return (
<div>
<div style={{ marginBottom: 16, display: 'flex', justifyContent: 'space-between' }}>
<h2>Cookie </h2>
{canExport && (
<Button type="primary" icon={<DownloadOutlined />} onClick={handleExport}>
CSV
<Space>
<Button
icon={<CopyOutlined />}
onClick={handleCopySelected}
disabled={selectedRowKeys.length === 0}
>
{selectedRowKeys.length > 0 && `(${selectedRowKeys.length})`}
</Button>
)}
{canExport && (
<Button type="primary" icon={<DownloadOutlined />} onClick={handleExport}>
CSV
</Button>
)}
</Space>
</div>
<Row gutter={16} style={{ marginBottom: 16 }}>
<Col span={6}>
@@ -96,6 +143,10 @@ export default function CookiePage() {
</Col>
</Row>
<Table
rowSelection={{
selectedRowKeys,
onChange: (keys) => setSelectedRowKeys(keys),
}}
columns={columns}
dataSource={cookies}
rowKey="id"