增加斗鱼自定义CK筛选功能
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useState, useCallback } from 'react';
|
||||
import { Table, Button, Card, Row, Col, Statistic, Tag, Popconfirm, Space, Typography, Input, theme, Dropdown, Tooltip } from 'antd';
|
||||
import { message } from '../utils/antdMessage';
|
||||
import { DownloadOutlined, DeleteOutlined, CopyOutlined, SearchOutlined, LoadingOutlined, ReloadOutlined } from '@ant-design/icons';
|
||||
import { DownloadOutlined, DeleteOutlined, CopyOutlined, SearchOutlined, LoadingOutlined, ReloadOutlined, FilterOutlined } from '@ant-design/icons';
|
||||
import { cookieApi, type BasicSummary, type CookieCheckResult, type CookieItem } from '../api/modules';
|
||||
import { usePermissions } from '../hooks/usePermissions';
|
||||
import { formatTime } from '../utils/time';
|
||||
@@ -37,12 +37,24 @@ function copyToClipboard(text: string): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
function parseAccountNames(text: string): string[] {
|
||||
const seen = new Set<string>();
|
||||
return text
|
||||
.replace(/\r\n/g, '\n')
|
||||
.replace(/\r/g, '\n')
|
||||
.split('\n')
|
||||
.map((name) => name.trim())
|
||||
.filter((name) => name.length > 0 && !seen.has(name) && seen.add(name));
|
||||
}
|
||||
|
||||
export default function CookiePage() {
|
||||
const { token } = theme.useToken();
|
||||
const [cookies, setCookies] = useState<CookieItem[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
||||
const [searchText, setSearchText] = useState('');
|
||||
const [customNamesText, setCustomNamesText] = useState('');
|
||||
const [customAccountNames, setCustomAccountNames] = useState<string[]>([]);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [summary, setSummary] = useState<BasicSummary>({ total: 0, assigned_count: 0, unassigned_count: 0 });
|
||||
const [pageSize, setPageSize] = useState(() => {
|
||||
@@ -148,6 +160,7 @@ export default function CookiePage() {
|
||||
page: currentPage,
|
||||
page_size: pageSize,
|
||||
search: searchText.trim() || undefined,
|
||||
account_names: customAccountNames.length > 0 ? customAccountNames.join('\n') : undefined,
|
||||
include_cookie: false,
|
||||
});
|
||||
setCookies(data.items);
|
||||
@@ -174,7 +187,7 @@ export default function CookiePage() {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [currentPage, pageSize, searchText]);
|
||||
}, [currentPage, pageSize, searchText, customAccountNames]);
|
||||
|
||||
const loadSummary = useCallback(async () => {
|
||||
try {
|
||||
@@ -195,19 +208,60 @@ export default function CookiePage() {
|
||||
|
||||
const handleExport = async (format: string = 'csv') => {
|
||||
try {
|
||||
const blob = await cookieApi.exportCsv(format);
|
||||
const blob = await cookieApi.exportCsv(
|
||||
format,
|
||||
customAccountNames.length > 0 ? customAccountNames.join('\n') : undefined,
|
||||
);
|
||||
const url = URL.createObjectURL(blob instanceof Blob ? blob : new Blob([blob]));
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = format === 'custom' ? 'cookies_custom.txt' : 'cookies.csv';
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
message.success('已导出');
|
||||
message.success(customAccountNames.length > 0 ? '已导出匹配的 Cookie' : '已导出');
|
||||
} catch (e: unknown) {
|
||||
message.error(getErrorMessage(e));
|
||||
}
|
||||
};
|
||||
|
||||
const handleApplyCustomFilter = () => {
|
||||
const names = parseAccountNames(customNamesText);
|
||||
if (names.length === 0) {
|
||||
message.warning('请先粘贴斗鱼账户名,每行一个');
|
||||
return;
|
||||
}
|
||||
setCustomAccountNames(names);
|
||||
setSelectedRowKeys([]);
|
||||
setCurrentPage(1);
|
||||
message.success(`已载入 ${names.length} 个账户名,正在筛选 Cookie`);
|
||||
};
|
||||
|
||||
const handleClearCustomFilter = () => {
|
||||
setCustomNamesText('');
|
||||
setCustomAccountNames([]);
|
||||
setSelectedRowKeys([]);
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
const handleCopyCustomCookies = async () => {
|
||||
if (customAccountNames.length === 0) {
|
||||
message.warning('请先筛选自定义账户名');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const blob = await cookieApi.exportCsv('custom', customAccountNames.join('\n'));
|
||||
const text = blob instanceof Blob ? await blob.text() : String(blob);
|
||||
if (!text.trim()) {
|
||||
message.warning('没有找到对应的 Cookie');
|
||||
return;
|
||||
}
|
||||
await copyToClipboard(text);
|
||||
message.success(`已复制 ${total} 条匹配的自定义 CK`);
|
||||
} catch (e: unknown) {
|
||||
message.error(getErrorMessage(e) || '复制失败');
|
||||
}
|
||||
};
|
||||
|
||||
const handleCopyCookie = async (record: CookieItem) => {
|
||||
try {
|
||||
const detail = await cookieApi.get(record.id);
|
||||
@@ -475,6 +529,30 @@ export default function CookiePage() {
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
<Card size="small" title="获取自定义 CK" style={{ marginBottom: 16 }}>
|
||||
<Space direction="vertical" style={{ width: '100%' }} size={8}>
|
||||
<Input.TextArea
|
||||
value={customNamesText}
|
||||
onChange={(e) => setCustomNamesText(e.target.value)}
|
||||
placeholder="从 Excel 复制斗鱼账户名后粘贴到这里,每行一个"
|
||||
autoSize={{ minRows: 3, maxRows: 7 }}
|
||||
/>
|
||||
<Space wrap>
|
||||
<Button type="primary" icon={<FilterOutlined />} onClick={handleApplyCustomFilter}>
|
||||
筛选自定义 CK
|
||||
</Button>
|
||||
<Button icon={<CopyOutlined />} onClick={handleCopyCustomCookies} disabled={customAccountNames.length === 0}>
|
||||
复制匹配 CK
|
||||
</Button>
|
||||
<Button onClick={handleClearCustomFilter} disabled={!customNamesText && customAccountNames.length === 0}>
|
||||
清空
|
||||
</Button>
|
||||
{customAccountNames.length > 0 && (
|
||||
<Text type="secondary">已载入 {customAccountNames.length} 个账户名,匹配结果共 {total} 条</Text>
|
||||
)}
|
||||
</Space>
|
||||
</Space>
|
||||
</Card>
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Input.Search
|
||||
placeholder="搜索账号或分配客服"
|
||||
|
||||
Reference in New Issue
Block a user