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