修复 antd 弃用警告

This commit is contained in:
yml2213
2026-07-24 12:48:02 +08:00
parent a13dde57dd
commit 6840728da6
17 changed files with 225 additions and 138 deletions
+33 -29
View File
@@ -1,10 +1,11 @@
import { lazy, Suspense, useState, useCallback, type ReactNode } from 'react';
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
import { ConfigProvider, Spin, theme } from 'antd';
import { App as AntdApp, ConfigProvider, Spin, theme } from 'antd';
import zhCN from 'antd/locale/zh_CN';
import { getUser } from './store/auth';
import { ThemeProvider } from './store/theme';
import { useTheme } from './store/useTheme';
import AntdMessageBridge from './utils/AntdMessageBridge';
const LoginPage = lazy(() => import('./pages/LoginPage'));
const MainLayout = lazy(() => import('./layouts/MainLayout'));
@@ -51,34 +52,37 @@ function AppContent() {
},
}}
>
<BrowserRouter>
<Routes>
<Route path="/login" element={lazyRoute(<LoginPage onLogin={refreshAuth} />)} />
<Route
path="/"
element={
isLoggedIn
? lazyRoute(<MainLayout key={authVersion} onLogout={refreshAuth} />)
: <Navigate to="/login" replace />
}
>
<Route index element={lazyRoute(<DashboardPage />)} />
<Route path="accounts" element={lazyRoute(<AccountsPage />)} />
<Route path="account-check" element={lazyRoute(<AccountCheckPage />)} />
<Route path="assignments" element={lazyRoute(<AssignmentsPage />)} />
<Route path="login-tasks" element={lazyRoute(<LoginTasksPage />)} />
<Route path="cookies" element={lazyRoute(<CookiePage />)} />
<Route path="huya/accounts" element={lazyRoute(<HuyaAccountsPage />)} />
<Route path="huya/register" element={lazyRoute(<HuyaRegisterPage />)} />
<Route path="huya/assignments" element={lazyRoute(<HuyaAssignmentsPage />)} />
<Route path="huya/cookies" element={lazyRoute(<HuyaCookiePage />)} />
<Route path="huya/tasks" element={lazyRoute(<HuyaTasksPage />)} />
<Route path="proxy" element={lazyRoute(<ProxyPage />)} />
<Route path="users" element={lazyRoute(<UsersPage />)} />
</Route>
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</BrowserRouter>
<AntdApp>
<AntdMessageBridge />
<BrowserRouter>
<Routes>
<Route path="/login" element={lazyRoute(<LoginPage onLogin={refreshAuth} />)} />
<Route
path="/"
element={
isLoggedIn
? lazyRoute(<MainLayout key={authVersion} onLogout={refreshAuth} />)
: <Navigate to="/login" replace />
}
>
<Route index element={lazyRoute(<DashboardPage />)} />
<Route path="accounts" element={lazyRoute(<AccountsPage />)} />
<Route path="account-check" element={lazyRoute(<AccountCheckPage />)} />
<Route path="assignments" element={lazyRoute(<AssignmentsPage />)} />
<Route path="login-tasks" element={lazyRoute(<LoginTasksPage />)} />
<Route path="cookies" element={lazyRoute(<CookiePage />)} />
<Route path="huya/accounts" element={lazyRoute(<HuyaAccountsPage />)} />
<Route path="huya/register" element={lazyRoute(<HuyaRegisterPage />)} />
<Route path="huya/assignments" element={lazyRoute(<HuyaAssignmentsPage />)} />
<Route path="huya/cookies" element={lazyRoute(<HuyaCookiePage />)} />
<Route path="huya/tasks" element={lazyRoute(<HuyaTasksPage />)} />
<Route path="proxy" element={lazyRoute(<ProxyPage />)} />
<Route path="users" element={lazyRoute(<UsersPage />)} />
</Route>
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</BrowserRouter>
</AntdApp>
</ConfigProvider>
);
}
+1 -1
View File
@@ -193,7 +193,7 @@ export default function MainLayout({ onLogout }: { onLogout?: () => void }) {
)}
{collapsed ? (
<>
<Space direction="vertical" style={{ width: '100%' }}>
<Space orientation="vertical" style={{ width: '100%' }}>
<Dropdown
menu={{ items: THEME_OPTIONS.map(o => ({ key: o.key, label: o.label, icon: o.icon, onClick: () => setMode(o.key) })) }}
trigger={['click']}
+28 -23
View File
@@ -1,7 +1,8 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
Button, Card, Col, Input, InputNumber, message, Popconfirm, Row, Space, Statistic, Switch, Table, Tag, Typography,
Button, Card, Col, Input, InputNumber, Popconfirm, Row, Space, Statistic, Switch, Table, Tag, Typography,
} from 'antd';
import { message } from '../utils/antdMessage';
import type { TableProps } from 'antd';
import { DownloadOutlined, PlayCircleOutlined, ReloadOutlined, StopOutlined } from '@ant-design/icons';
import { accountCheckApi, type AccountCheckBatch, type AccountCheckItem } from '../api/modules';
@@ -163,7 +164,7 @@ export default function AccountCheckPage() {
return () => window.clearInterval(timer);
}, [batchId, isRunning, refreshBatch]);
const statusCounts = batch?.status_counts || {};
const statusCounts = useMemo(() => batch?.status_counts || {}, [batch?.status_counts]);
const categoryStats = useMemo(() => [
{ title: '已注销', value: statusCounts.account_cancelled || 0 },
{ title: '密码错误', value: statusCounts.password_wrong || 0 },
@@ -247,11 +248,11 @@ export default function AccountCheckPage() {
];
return (
<Space direction="vertical" size={16} style={{ width: '100%' }}>
<Space orientation="vertical" size={16} style={{ width: '100%' }}>
<Title level={3} style={{ margin: 0 }}></Title>
<Card title="导入账号">
<Space direction="vertical" size={12} style={{ width: '100%' }}>
<Space orientation="vertical" size={12} style={{ width: '100%' }}>
<TextArea
rows={9}
value={text}
@@ -273,28 +274,32 @@ export default function AccountCheckPage() {
</Col>
<Col xs={8} md={4}>
<Text type="secondary"></Text>
<InputNumber
min={0}
max={3600}
step={30}
value={maxTotalTime}
onChange={(value) => setMaxTotalTime(Number(value ?? 0))}
disabled={isRunning}
addonAfter="秒"
style={{ width: '100%' }}
/>
<Space.Compact style={{ width: '100%' }}>
<InputNumber
min={0}
max={3600}
step={30}
value={maxTotalTime}
onChange={(value) => setMaxTotalTime(Number(value ?? 0))}
disabled={isRunning}
style={{ width: '100%' }}
/>
<Button disabled></Button>
</Space.Compact>
</Col>
<Col xs={8} md={4}>
<Text type="secondary"></Text>
<InputNumber
min={0}
max={50}
value={maxLoginRetries}
onChange={(value) => setMaxLoginRetries(Number(value ?? 0))}
disabled={isRunning}
addonAfter="次"
style={{ width: '100%' }}
/>
<Space.Compact style={{ width: '100%' }}>
<InputNumber
min={0}
max={50}
value={maxLoginRetries}
onChange={(value) => setMaxLoginRetries(Number(value ?? 0))}
disabled={isRunning}
style={{ width: '100%' }}
/>
<Button disabled></Button>
</Space.Compact>
</Col>
<Col xs={12} md={4}>
<Text type="secondary"></Text>
+2 -1
View File
@@ -1,8 +1,9 @@
import { useEffect, useState, useMemo, useCallback } from 'react';
import {
Table, Button, Modal, Input, Select, message, Popconfirm, Typography, Tag, Space,
Table, Button, Modal, Input, Select, Popconfirm, Typography, Tag, Space,
Row, Col, Card, Statistic,
} from 'antd';
import { message } from '../utils/antdMessage';
import type { TableProps } from 'antd';
import { ImportOutlined, DeleteOutlined, TagOutlined, FilterOutlined } from '@ant-design/icons';
import { accountApi, userApi, type AccountItem, type UserInfo } from '../api/modules';
+2 -1
View File
@@ -1,8 +1,9 @@
import { useEffect, useState, useMemo } from 'react';
import {
Card, Table, Button, Select, Input, Tag, Row, Col, Statistic,
message, Space, Tabs, Typography, Badge, theme,
Space, Tabs, Typography, Badge, theme,
} from 'antd';
import { message } from '../utils/antdMessage';
import {
UserOutlined, CheckCircleOutlined, TeamOutlined,
SwapOutlined, ClearOutlined, UsergroupAddOutlined,
+2 -1
View File
@@ -1,5 +1,6 @@
import { useEffect, useState, useCallback } from 'react';
import { Table, Button, Card, Row, Col, Statistic, message, Tag, Popconfirm, Space, Typography, Input, theme, Dropdown } from 'antd';
import { Table, Button, Card, Row, Col, Statistic, Tag, Popconfirm, Space, Typography, Input, theme, Dropdown } from 'antd';
import { message } from '../utils/antdMessage';
import { DownloadOutlined, DeleteOutlined, CopyOutlined, SearchOutlined } from '@ant-design/icons';
import { cookieApi, type CookieItem } from '../api/modules';
import { usePermissions } from '../hooks/usePermissions';
+7 -6
View File
@@ -1,7 +1,8 @@
import { useCallback, useEffect, useMemo, useState } from 'react';
import {
Button, Card, Col, Input, message, Modal, Popconfirm, Row, Select, Space, Statistic, Table, Tag, Typography,
Button, Card, Col, Input, Modal, Popconfirm, Row, Select, Space, Statistic, Table, Tag, Typography,
} from 'antd';
import { message } from '../utils/antdMessage';
import type { TableProps } from 'antd';
import { DeleteOutlined, FilterOutlined, ImportOutlined, LoginOutlined, MobileOutlined, ReloadOutlined, SearchOutlined, TagOutlined } from '@ant-design/icons';
import {
@@ -376,7 +377,7 @@ export default function HuyaAccountsPage() {
title: '虎牙账号',
width: 180,
render: (_: unknown, record) => (
<Space direction="vertical" size={0}>
<Space orientation="vertical" size={0}>
<Text strong>{record.nickname || record.username || record.uid || '-'}</Text>
<Text type="secondary" style={{ fontSize: 12 }}>
UID {record.uid || record.yyuid || '-'}
@@ -440,7 +441,7 @@ export default function HuyaAccountsPage() {
width: 160,
ellipsis: true,
render: (value: string, record) => value ? (
<Space direction="vertical" size={0}>
<Space orientation="vertical" size={0}>
<Text>{value}</Text>
{record.game_channel ? (
<Text type="secondary" style={{ fontSize: 12 }}>{record.game_channel}</Text>
@@ -659,7 +660,7 @@ export default function HuyaAccountsPage() {
confirmLoading={importing}
width={720}
>
<Space direction="vertical" style={{ width: '100%' }} size={12}>
<Space orientation="vertical" style={{ width: '100%' }} size={12}>
<Input
placeholder="标签,可选"
value={importTag}
@@ -711,7 +712,7 @@ export default function HuyaAccountsPage() {
closable={!passwordImporting}
width={720}
>
<Space direction="vertical" style={{ width: '100%' }} size={12}>
<Space orientation="vertical" style={{ width: '100%' }} size={12}>
<TextArea
rows={10}
value={passwordImportText}
@@ -757,7 +758,7 @@ export default function HuyaAccountsPage() {
closable={!(smsSending || smsLogging)}
width={520}
>
<Space direction="vertical" style={{ width: '100%' }} size={12}>
<Space orientation="vertical" style={{ width: '100%' }} size={12}>
<Input
value={smsPhone}
onChange={(e) => setSmsPhone(e.target.value)}
@@ -1,7 +1,8 @@
import { useEffect, useMemo, useState } from 'react';
import {
Badge, Button, Card, Col, Input, message, Row, Select, Space, Statistic, Table, Tabs, Tag, theme, Typography,
Badge, Button, Card, Col, Input, Row, Select, Space, Statistic, Table, Tabs, Tag, theme, Typography,
} from 'antd';
import { message } from '../utils/antdMessage';
import {
CheckCircleOutlined, ClearOutlined, SwapOutlined, TeamOutlined, UsergroupAddOutlined, UserOutlined,
} from '@ant-design/icons';
@@ -178,7 +179,7 @@ export default function HuyaAssignmentsPage() {
{
title: '虎牙账号',
render: (_: unknown, record: HuyaAccountItem) => (
<Space direction="vertical" size={0}>
<Space orientation="vertical" size={0}>
<Text strong>{accountName(record)}</Text>
<Text type="secondary" style={{ fontSize: 12 }}>UID {record.uid || record.yyuid || '-'}</Text>
</Space>
+2 -1
View File
@@ -1,7 +1,8 @@
import { useCallback, useEffect, useState } from 'react';
import {
Button, Card, Col, Dropdown, Input, message, Popconfirm, Row, Space, Statistic, Table, Tag, theme, Typography,
Button, Card, Col, Dropdown, Input, Popconfirm, Row, Space, Statistic, Table, Tag, theme, Typography,
} from 'antd';
import { message } from '../utils/antdMessage';
import { CopyOutlined, DeleteOutlined, DownloadOutlined, SearchOutlined } from '@ant-design/icons';
import { huyaApi, type HuyaCookieItem } from '../api/modules';
import { usePermissions } from '../hooks/usePermissions';
+4 -3
View File
@@ -1,7 +1,8 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
Button, Card, Col, Input, InputNumber, message, Row, Segmented, Space, Statistic, Switch, Table, Tag, Typography,
Button, Card, Col, Input, InputNumber, Row, Segmented, Space, Statistic, Switch, Table, Tag, Typography,
} from 'antd';
import { message } from '../utils/antdMessage';
import type { TableProps } from 'antd';
import {
DownloadOutlined, PlayCircleOutlined, RedoOutlined, ReloadOutlined, StopOutlined,
@@ -584,11 +585,11 @@ export default function HuyaRegisterPage() {
];
return (
<Space direction="vertical" size={16} style={{ width: '100%' }}>
<Space orientation="vertical" size={16} style={{ width: '100%' }}>
<Title level={3} style={{ margin: 0 }}></Title>
<Card title="手机号池">
<Space direction="vertical" size={12} style={{ width: '100%' }}>
<Space orientation="vertical" size={12} style={{ width: '100%' }}>
<TextArea
rows={9}
value={text}
+46 -39
View File
@@ -1,7 +1,8 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
Button, Card, Col, DatePicker, Dropdown, Form, Input, InputNumber, message, Modal, QRCode, Radio, Row, Select, Space, Table, Tag, Tooltip, Typography, theme,
Button, Card, Col, DatePicker, Dropdown, Form, Input, InputNumber, Modal, QRCode, Radio, Row, Select, Space, Table, Tag, Tooltip, Typography, theme,
} from 'antd';
import { message } from '../utils/antdMessage';
import type { MenuProps, TableProps } from 'antd';
import type { Dayjs } from 'dayjs';
import type { MouseEvent as ReactMouseEvent } from 'react';
@@ -1164,7 +1165,7 @@ export default function HuyaTasksPage() {
title: '虎牙 CK',
width: 250,
render: (_: unknown, record) => (
<Space direction="vertical" size={1} style={{ width: '100%' }}>
<Space orientation="vertical" size={1} style={{ width: '100%' }}>
<Space size={6} wrap>
<Text strong>{accountDisplayName(record)}</Text>
{record.tag ? <Tag color={tagColorMap[record.tag]}>{record.tag}</Tag> : null}
@@ -1191,7 +1192,7 @@ export default function HuyaTasksPage() {
width: 170,
ellipsis: true,
render: (value: string, record) => value ? (
<Space direction="vertical" size={0}>
<Space orientation="vertical" size={0}>
<Text>{value}</Text>
{record.game_channel ? <Text type="secondary" style={{ fontSize: 12 }}>{record.game_channel}</Text> : null}
</Space>
@@ -1214,7 +1215,7 @@ export default function HuyaTasksPage() {
const product = taskProductText(task);
if (!task || !product) return <Text type="secondary">-</Text>;
return (
<Space direction="vertical" size={1}>
<Space orientation="vertical" size={1}>
<Text ellipsis style={{ maxWidth: 170 }}>{product}</Text>
<Tag color={STATUS_COLORS[task.status] || 'default'} style={{ width: 'fit-content' }}>
{taskTypes[task.task_type] || task.task_type}
@@ -1250,7 +1251,7 @@ export default function HuyaTasksPage() {
const latest = latestTaskByAccount.get(record.id);
if (!latest) return <Text type="secondary"></Text>;
return (
<Space direction="vertical" size={2} style={{ width: '100%' }}>
<Space orientation="vertical" size={2} style={{ width: '100%' }}>
<Text ellipsis style={{ maxWidth: 238 }}>
{taskTypes[latest.task_type] || latest.task_type}{latest.message || '-'}
</Text>
@@ -1294,7 +1295,7 @@ export default function HuyaTasksPage() {
title: '虎牙 CK',
width: 230,
render: (_: unknown, record) => (
<Space direction="vertical" size={1}>
<Space orientation="vertical" size={1}>
<Space size={6} wrap>
<Text strong>{accountDisplayName(record)}</Text>
{record.tag ? <Tag color={tagColorMap[record.tag]}>{record.tag}</Tag> : null}
@@ -1315,7 +1316,7 @@ export default function HuyaTasksPage() {
dataIndex: 'game_name',
ellipsis: true,
render: (value: string, record) => value ? (
<Space direction="vertical" size={0}>
<Space orientation="vertical" size={0}>
<Text>{value}</Text>
{record.game_channel ? <Text type="secondary" style={{ fontSize: 12 }}>{record.game_channel}</Text> : null}
</Space>
@@ -1482,7 +1483,7 @@ export default function HuyaTasksPage() {
{accountContextMenu.accountIds.length > 1 ? '右键批量动作' : '右键账号动作'}
</Text>
</div>
<Space direction="vertical" size={2} style={{ width: '100%' }}>
<Space orientation="vertical" size={2} style={{ width: '100%' }}>
{QUICK_ACTIONS.map((item) => (
<Button
key={item.key}
@@ -1626,17 +1627,19 @@ export default function HuyaTasksPage() {
</div>
<div style={{ minHeight: 0, overflowY: 'auto', overflowX: 'hidden' }}>
<Space direction="vertical" size={12} style={{ width: '100%' }}>
<Space orientation="vertical" size={12} style={{ width: '100%' }}>
<Card size="small" title="批量动作" extra={<Tag color={selectedIds.length ? 'blue' : 'default'}>{selectedAccountText}</Tag>}>
<Space direction="vertical" size={10} style={{ width: '100%' }}>
<InputNumber
min={1}
max={10}
value={concurrency}
onChange={(value) => setConcurrency(value || 1)}
addonBefore="并发"
style={{ width: '100%' }}
/>
<Space orientation="vertical" size={10} style={{ width: '100%' }}>
<Space.Compact style={{ width: '100%' }}>
<Button disabled></Button>
<InputNumber
min={1}
max={10}
value={concurrency}
onChange={(value) => setConcurrency(value || 1)}
style={{ width: '100%' }}
/>
</Space.Compact>
<Select
value={selectedTaskType}
onChange={setSelectedTaskType}
@@ -1685,7 +1688,7 @@ export default function HuyaTasksPage() {
</Button>
)}
>
<Space direction="vertical" size={10} style={{ width: '100%' }}>
<Space orientation="vertical" size={10} style={{ width: '100%' }}>
{goodsCategories.length > 0 ? (
<Select
value={selectedGoodsCategory}
@@ -1707,12 +1710,14 @@ export default function HuyaTasksPage() {
style={{ width: '100%' }}
filterOption={(input, option) => String(option?.label || '').toLowerCase().includes(input.toLowerCase())}
/>
<Input
addonBefore="PID"
value={selectedExchangeGoodsId}
onChange={(event) => setSelectedExchangeGoodsId(event.target.value.trim())}
placeholder="商品 PID"
/>
<Space.Compact style={{ width: '100%' }}>
<Button disabled>PID</Button>
<Input
value={selectedExchangeGoodsId}
onChange={(event) => setSelectedExchangeGoodsId(event.target.value.trim())}
placeholder="商品 PID"
/>
</Space.Compact>
<DatePicker
showTime
allowClear
@@ -1747,7 +1752,7 @@ export default function HuyaTasksPage() {
</Button>
)}
>
<Space direction="vertical" size={10} style={{ width: '100%' }}>
<Space orientation="vertical" size={10} style={{ width: '100%' }}>
<Select
showSearch
allowClear
@@ -1758,14 +1763,16 @@ export default function HuyaTasksPage() {
style={{ width: '100%' }}
filterOption={(input, option) => String(option?.label || '').toLowerCase().includes(input.toLowerCase())}
/>
<InputNumber
min={1}
max={999}
value={rechargeCount}
onChange={(value) => setRechargeCount(value || 1)}
addonAfter="份"
style={{ width: '100%' }}
/>
<Space.Compact style={{ width: '100%' }}>
<InputNumber
min={1}
max={999}
value={rechargeCount}
onChange={(value) => setRechargeCount(value || 1)}
style={{ width: '100%' }}
/>
<Button disabled></Button>
</Space.Compact>
<Radio.Group value={rechargePayChannel} onChange={(event) => setRechargePayChannel(event.target.value)}>
<Radio value="Weixin"></Radio>
<Radio value="Zfb"></Radio>
@@ -1862,7 +1869,7 @@ export default function HuyaTasksPage() {
]}
width={860}
>
<Space direction="vertical" size={10} style={{ width: '100%' }}>
<Space orientation="vertical" size={10} style={{ width: '100%' }}>
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' }}>
<Input.Search
allowClear
@@ -1919,7 +1926,7 @@ export default function HuyaTasksPage() {
footer={null}
width={760}
>
<Space direction="vertical" size={10} style={{ width: '100%' }}>
<Space orientation="vertical" size={10} style={{ width: '100%' }}>
<Text type="secondary">
{exchangeRecordsAccountName}{exchangeRecordsResult?.sid ? ` / SID ${String(exchangeRecordsResult.sid)}` : ''}
</Text>
@@ -1944,7 +1951,7 @@ export default function HuyaTasksPage() {
>
{qrTask && (
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 12, padding: '8px 0 12px' }}>
<Space direction="vertical" size={4} style={{ width: '100%', textAlign: 'center' }}>
<Space orientation="vertical" size={4} style={{ width: '100%', textAlign: 'center' }}>
<Text strong>{qrAccountName}</Text>
<Tag
color={qrBindReady ? 'gold' : qrBindPhase === 'role_timeout' || qrQueryFinished ? 'orange' : 'processing'}
@@ -1979,7 +1986,7 @@ export default function HuyaTasksPage() {
<Text type="secondary"></Text>
)}
{qrRoleLine ? (
<Space direction="vertical" size={2} style={{ width: '100%', textAlign: 'center' }}>
<Space orientation="vertical" size={2} style={{ width: '100%', textAlign: 'center' }}>
{qrGameTitle ? <Text type="secondary">{qrGameTitle}</Text> : null}
<Text strong>{qrRoleLine}</Text>
</Space>
@@ -2017,7 +2024,7 @@ export default function HuyaTasksPage() {
>
{payTask && (
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 12, padding: '8px 0 12px' }}>
<Space direction="vertical" size={2} style={{ width: '100%', textAlign: 'center' }}>
<Space orientation="vertical" size={2} style={{ width: '100%', textAlign: 'center' }}>
<Text strong>{payProductName || '充值商品'}</Text>
<Text type="secondary">
{payChannelLabel || '支付'}{payAmountText ? ` / ${payAmountText}` : ''}{payAccountName ? ` / ${payAccountName}` : ''}
+2 -1
View File
@@ -1,5 +1,6 @@
import { useState } from 'react';
import { Card, Form, Input, Button, message, Typography } from 'antd';
import { Card, Form, Input, Button, Typography } from 'antd';
import { message } from '../utils/antdMessage';
import { LockOutlined, UserOutlined } from '@ant-design/icons';
import { useNavigate } from 'react-router-dom';
import { authApi } from '../api/modules';
+35 -28
View File
@@ -1,7 +1,8 @@
import { useEffect, useState, useMemo, useCallback } from 'react';
import {
Table, Button, Select, message, Tag, Space, InputNumber, Tooltip, Popconfirm, theme, Modal, Form,
Table, Button, Select, Tag, Space, InputNumber, Tooltip, Popconfirm, theme, Modal, Form,
} from 'antd';
import { message } from '../utils/antdMessage';
import {
PlayCircleOutlined, StopOutlined, FilterOutlined, ReloadOutlined, DeleteOutlined,
SettingOutlined, SafetyCertificateOutlined,
@@ -503,43 +504,49 @@ export default function LoginTasksPage() {
label="并发数"
tooltip="同时登录的账号数。1 为顺序执行,最多 10。"
>
<InputNumber
min={1}
max={10}
value={concurrency}
onChange={(v) => setConcurrency(v || 1)}
style={{ width: 120 }}
addonAfter="个"
/>
<Space.Compact>
<InputNumber
min={1}
max={10}
value={concurrency}
onChange={(v) => setConcurrency(v || 1)}
style={{ width: 120 }}
/>
<Button disabled></Button>
</Space.Compact>
</Form.Item>
<Form.Item
label="单账号超时"
tooltip="单个账号登录的总时长上限,超时则放弃。0 表示不限。"
>
<InputNumber
min={0}
max={3600}
step={30}
value={maxTotalTime}
onChange={(v) => setMaxTotalTime(v ?? 0)}
style={{ width: 120 }}
addonAfter="秒"
placeholder="0=不限"
/>
<Space.Compact>
<InputNumber
min={0}
max={3600}
step={30}
value={maxTotalTime}
onChange={(v) => setMaxTotalTime(v ?? 0)}
style={{ width: 120 }}
placeholder="0=不限"
/>
<Button disabled></Button>
</Space.Compact>
</Form.Item>
<Form.Item
label="登录整体重试次数"
tooltip="单个账号最多重试多少轮(每轮换新代理)。0 表示无限重试直到成功或超时。"
>
<InputNumber
min={0}
max={50}
value={maxLoginRetries}
onChange={(v) => setMaxLoginRetries(v ?? 0)}
style={{ width: 120 }}
addonAfter="次"
placeholder="0=无限"
/>
<Space.Compact>
<InputNumber
min={0}
max={50}
value={maxLoginRetries}
onChange={(v) => setMaxLoginRetries(v ?? 0)}
style={{ width: 120 }}
placeholder="0=无限"
/>
<Button disabled></Button>
</Space.Compact>
</Form.Item>
</Form>
</Modal>
+2 -1
View File
@@ -1,5 +1,6 @@
import { useEffect, useState, useCallback } from 'react';
import { Form, Input, Switch, Button, Card, Select, message, Row, Col } from 'antd';
import { Form, Input, Switch, Button, Card, Select, Row, Col } from 'antd';
import { message } from '../utils/antdMessage';
import { proxyApi, type ProxyConfig, type PlatformInfo } from '../api/modules';
import RealtimeLogPanel from '../components/RealtimeLogPanel';
import { useWebSocketLogs } from '../hooks/useWebSocketLogs';
+2 -1
View File
@@ -1,8 +1,9 @@
import { useEffect, useState, useCallback } from 'react';
import {
Table, Button, Modal, Form, Input, Select, Tag, Popconfirm, message, Space,
Table, Button, Modal, Form, Input, Select, Tag, Popconfirm, Space,
Checkbox, Divider, Alert, Tooltip,
} from 'antd';
import { message } from '../utils/antdMessage';
import { PlusOutlined, EditOutlined, DeleteOutlined, SafetyOutlined } from '@ant-design/icons';
import { userApi, type UserInfo } from '../api/modules';
import { usePermissions } from '../hooks/usePermissions';
@@ -0,0 +1,16 @@
import { useEffect } from 'react';
import { App as AntdApp } from 'antd';
import { setAntdMessageApi } from './antdMessage';
export default function AntdMessageBridge() {
const { message } = AntdApp.useApp();
useEffect(() => {
setAntdMessageApi(message);
return () => {
setAntdMessageApi(null);
};
}, [message]);
return null;
}
+38
View File
@@ -0,0 +1,38 @@
import type { Key } from 'react';
import type {
ArgsProps,
JointContent,
MessageInstance,
MessageType,
TypeOpen,
} from 'antd/es/message/interface';
let messageApi: MessageInstance | null = null;
const noopMessage = Object.assign(() => undefined, {
then: (
onfulfilled?: ((value: boolean) => unknown) | null,
onrejected?: ((reason: unknown) => unknown) | null,
) => Promise.resolve(true).then(onfulfilled ?? undefined, onrejected ?? undefined),
}) as MessageType;
function createTypeOpen(type: 'info' | 'success' | 'error' | 'warning' | 'loading'): TypeOpen {
return (content: JointContent, duration?: number | VoidFunction, onClose?: VoidFunction) => {
if (!messageApi) return noopMessage;
return messageApi[type](content, duration, onClose);
};
}
export function setAntdMessageApi(api: MessageInstance | null) {
messageApi = api;
}
export const message = {
info: createTypeOpen('info'),
success: createTypeOpen('success'),
error: createTypeOpen('error'),
warning: createTypeOpen('warning'),
loading: createTypeOpen('loading'),
open: (args: ArgsProps) => messageApi?.open(args) ?? noopMessage,
destroy: (key?: Key) => messageApi?.destroy(key),
} satisfies MessageInstance;