优化登录弹窗
This commit is contained in:
@@ -124,8 +124,8 @@ class AccountOut(BaseModel):
|
||||
# ---- 登录任务 ----
|
||||
class LoginBatchRequest(BaseModel):
|
||||
account_ids: list[int]
|
||||
max_login_retries: int = 0 # 登录整体重试次数,0=无限重试直到成功
|
||||
max_total_time: float = 0 # 单账号登录总时长上限,0=不限制
|
||||
max_login_retries: int = 0 # 登录整体重试次数,0=无限重试直到成功(后端兜底 20 次)
|
||||
max_total_time: float = 300 # 单账号登录总时长上限(秒),0=不限制
|
||||
concurrency: int = 3 # 并发数,1-10
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useEffect, useState, useMemo, useCallback } from 'react';
|
||||
import {
|
||||
Table, Button, Select, message, Tag, Space, InputNumber, Tooltip, Popconfirm, theme,
|
||||
Table, Button, Select, message, Tag, Space, InputNumber, Tooltip, Popconfirm, theme, Modal, Form,
|
||||
} from 'antd';
|
||||
import { PlayCircleOutlined, StopOutlined, FilterOutlined, ThunderboltOutlined, ReloadOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||
import { PlayCircleOutlined, StopOutlined, FilterOutlined, ReloadOutlined, DeleteOutlined, SettingOutlined } from '@ant-design/icons';
|
||||
import { accountApi, loginApi, type AccountItem, type LoginTaskItem } from '../api/modules';
|
||||
import RealtimeLogPanel from '../components/RealtimeLogPanel';
|
||||
import { usePermissions } from '../hooks/usePermissions';
|
||||
@@ -43,9 +43,20 @@ export default function LoginTasksPage() {
|
||||
const v = localStorage.getItem('login_concurrency');
|
||||
return v ? Math.max(1, Math.min(10, Number(v) || 3)) : 3;
|
||||
});
|
||||
const [maxTotalTime, setMaxTotalTime] = useState(() => {
|
||||
const v = localStorage.getItem('login_max_total_time');
|
||||
return v !== null ? Math.max(0, Number(v) || 0) : 300;
|
||||
});
|
||||
const [maxLoginRetries, setMaxLoginRetries] = useState(() => {
|
||||
const v = localStorage.getItem('login_max_login_retries');
|
||||
return v !== null ? Math.max(0, Number(v) || 0) : 0;
|
||||
});
|
||||
const [settingsOpen, setSettingsOpen] = useState(false);
|
||||
|
||||
// 值变化时自动持久化
|
||||
useEffect(() => { localStorage.setItem('login_concurrency', String(concurrency)); }, [concurrency]);
|
||||
useEffect(() => { localStorage.setItem('login_max_total_time', String(maxTotalTime)); }, [maxTotalTime]);
|
||||
useEffect(() => { localStorage.setItem('login_max_login_retries', String(maxLoginRetries)); }, [maxLoginRetries]);
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([]);
|
||||
const { logs, connected: wsConnected, connect: connectLogs } = useWebSocketLogs();
|
||||
const { can } = usePermissions();
|
||||
@@ -143,6 +154,8 @@ export default function LoginTasksPage() {
|
||||
const result = await loginApi.createBatch({
|
||||
account_ids: accountIds,
|
||||
concurrency,
|
||||
max_login_retries: maxLoginRetries,
|
||||
max_total_time: maxTotalTime,
|
||||
});
|
||||
setBatchId(result.batch_id);
|
||||
message.success(`已创建登录任务,共 ${result.count} 个账号`);
|
||||
@@ -329,18 +342,12 @@ export default function LoginTasksPage() {
|
||||
标签选中 {accounts.filter((a) => selectedTags.includes((a.tag || '').trim())).length} 个
|
||||
</span>
|
||||
)}
|
||||
<Tooltip title="同时登录的账号数,1为顺序执行">
|
||||
<Space size={4}>
|
||||
<ThunderboltOutlined style={{ color: token.colorTextSecondary }} />
|
||||
<InputNumber
|
||||
min={1}
|
||||
max={10}
|
||||
value={concurrency}
|
||||
onChange={(v) => setConcurrency(v || 1)}
|
||||
style={{ width: 50 }}
|
||||
size="small"
|
||||
/>
|
||||
</Space>
|
||||
<Tooltip title={`登录设置(并发 ${concurrency},超时 ${maxTotalTime || '∞'}s,重试 ${maxLoginRetries || '∞'})`}>
|
||||
<Button
|
||||
icon={<SettingOutlined />}
|
||||
onClick={() => setSettingsOpen(true)}
|
||||
size="small"
|
||||
/>
|
||||
</Tooltip>
|
||||
<Button
|
||||
type="primary"
|
||||
@@ -416,6 +423,72 @@ export default function LoginTasksPage() {
|
||||
spinWhenEmpty
|
||||
style={{ marginTop: 4 }}
|
||||
/>
|
||||
|
||||
<Modal
|
||||
title="登录设置"
|
||||
open={settingsOpen}
|
||||
onCancel={() => setSettingsOpen(false)}
|
||||
footer={[
|
||||
<Button
|
||||
key="reset"
|
||||
onClick={() => {
|
||||
setConcurrency(3);
|
||||
setMaxTotalTime(300);
|
||||
setMaxLoginRetries(0);
|
||||
}}
|
||||
>
|
||||
恢复默认
|
||||
</Button>,
|
||||
<Button key="ok" type="primary" onClick={() => setSettingsOpen(false)}>
|
||||
完成
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<Form layout="vertical" style={{ marginTop: 8 }}>
|
||||
<Form.Item
|
||||
label="并发数"
|
||||
tooltip="同时登录的账号数。1 为顺序执行,最多 10。"
|
||||
>
|
||||
<InputNumber
|
||||
min={1}
|
||||
max={10}
|
||||
value={concurrency}
|
||||
onChange={(v) => setConcurrency(v || 1)}
|
||||
style={{ width: 120 }}
|
||||
addonAfter="个"
|
||||
/>
|
||||
</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=不限"
|
||||
/>
|
||||
</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=无限"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user