一键检测重复-仓库管理

This commit is contained in:
yml2213
2026-08-08 20:51:50 +08:00
parent 65271124c0
commit b39780f26d
4 changed files with 211 additions and 4 deletions
+113 -3
View File
@@ -1,8 +1,8 @@
import { useEffect, useState, useCallback } from 'react';
import { Table, Button, Card, Row, Col, Statistic, Tag, Popconfirm, Space, Typography, Input, theme, Dropdown, Tooltip } from 'antd';
import { Table, Button, Card, Row, Col, Statistic, Tag, Popconfirm, Space, Typography, Input, theme, Dropdown, Tooltip, Modal, Alert, Empty } from 'antd';
import { message } from '../utils/antdMessage';
import { DownloadOutlined, DeleteOutlined, CopyOutlined, SearchOutlined, LoadingOutlined, ReloadOutlined, FilterOutlined } from '@ant-design/icons';
import { cookieApi, type BasicSummary, type CookieCheckResult, type CookieItem } from '../api/modules';
import { DownloadOutlined, DeleteOutlined, CopyOutlined, SearchOutlined, LoadingOutlined, ReloadOutlined, FilterOutlined, ScanOutlined } from '@ant-design/icons';
import { cookieApi, type BasicSummary, type CookieCheckResult, type CookieDuplicateGroup, type CookieDuplicateResponse, type CookieItem } from '../api/modules';
import { usePermissions } from '../hooks/usePermissions';
import { formatTime } from '../utils/time';
import { getErrorMessage } from '../utils/error';
@@ -65,6 +65,9 @@ export default function CookiePage() {
const [checkingIds, setCheckingIds] = useState<Set<number>>(new Set());
const [checkResults, setCheckResults] = useState<Map<number, CookieCheckResult>>(new Map());
const [reloginIds, setReloginIds] = useState<Set<number>>(new Set());
const [duplicateOpen, setDuplicateOpen] = useState(false);
const [duplicateLoading, setDuplicateLoading] = useState(false);
const [duplicateResult, setDuplicateResult] = useState<CookieDuplicateResponse | null>(null);
const { can } = usePermissions();
const canView = can('cookie:view');
@@ -153,6 +156,24 @@ export default function CookiePage() {
void handleCheck(ids);
};
const handleDuplicateCheck = async () => {
setDuplicateOpen(true);
setDuplicateLoading(true);
try {
const result = await cookieApi.duplicates();
setDuplicateResult(result);
if (result.duplicate_groups > 0) {
message.warning(`发现 ${result.duplicate_groups} 个重复账号,共 ${result.duplicate_rows} 条 CK 记录`);
} else {
message.success('未发现重复账号');
}
} catch (e: unknown) {
message.error(getErrorMessage(e));
} finally {
setDuplicateLoading(false);
}
};
const loadCookies = useCallback(async () => {
setLoading(true);
try {
@@ -440,11 +461,63 @@ export default function CookiePage() {
},
];
const duplicateColumns = [
{
title: '账号',
dataIndex: 'account_names',
width: 180,
ellipsis: true,
render: (names: string[]) => names.join(' / '),
},
{
title: 'CK 条数',
dataIndex: 'cookie_count',
width: 90,
align: 'center' as const,
render: (count: number) => <Tag color="error">{count}</Tag>,
},
{
title: '账号记录数',
dataIndex: 'account_count',
width: 110,
align: 'center' as const,
},
{
title: 'CK 记录 ID',
dataIndex: 'cookie_ids',
width: 220,
ellipsis: true,
render: (ids: number[]) => ids.join(', '),
},
{
title: '账号 ID',
dataIndex: 'account_ids',
width: 130,
ellipsis: true,
render: (ids: number[]) => ids.join(', '),
},
{
title: '最近记录',
width: 170,
align: 'center' as const,
render: (_: unknown, group: CookieDuplicateGroup) => formatTime(group.records[0]?.finished_at),
},
];
return (
<div>
<div style={{ marginBottom: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<h2 style={{ margin: 0 }}>Cookie </h2>
<Space>
{canView && (
<Button
icon={<ScanOutlined />}
loading={duplicateLoading}
onClick={handleDuplicateCheck}
>
</Button>
)}
<Button
icon={<CopyOutlined />}
onClick={handleCopySelected}
@@ -595,6 +668,43 @@ export default function CookiePage() {
}}
scroll={{ x: 1210 }}
/>
<Modal
title="数据库重复 CK 检测"
open={duplicateOpen}
onCancel={() => setDuplicateOpen(false)}
footer={null}
width={960}
>
{duplicateLoading ? (
<div style={{ padding: '48px 0', textAlign: 'center' }}>
<LoadingOutlined spin />
<Text style={{ marginLeft: 8 }}>...</Text>
</div>
) : duplicateResult ? (
<>
<Alert
type={duplicateResult.duplicate_groups > 0 ? 'warning' : 'success'}
showIcon
message={duplicateResult.duplicate_groups > 0
? `发现 ${duplicateResult.duplicate_groups} 个重复账号,共 ${duplicateResult.duplicate_rows} 条 CK 记录`
: '未发现重复账号'}
style={{ marginBottom: 16 }}
/>
{duplicateResult.groups.length > 0 ? (
<Table<CookieDuplicateGroup>
rowKey="account_key"
size="small"
pagination={{ pageSize: 10, showTotal: (count) => `${count}` }}
columns={duplicateColumns}
dataSource={duplicateResult.groups}
scroll={{ x: 900 }}
/>
) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="未发现重复账号" />
)}
</>
) : null}
</Modal>
</div>
);
}