import { useEffect, useState } from 'react' import { useDataProvider, useGetList } from 'ra-core' import { Alert, Box, Button, CircularProgress, Paper, Stack, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Typography, } from '@mui/material' import DeleteOutlined from '@mui/icons-material/DeleteOutlined' import PlayArrowOutlined from '@mui/icons-material/PlayArrowOutlined' import SecurityOutlined from '@mui/icons-material/SecurityOutlined' import StopOutlined from '@mui/icons-material/StopOutlined' const statusLabels = { created: '已创建', running: '运行中', exited: '已停止', restarting: '重启中', paused: '已暂停', } function Status({ state }) { const color = state === 'running' ? 'success.main' : state === 'exited' ? 'warning.main' : 'text.secondary' return {statusLabels[state] || state} } function RuntimeActions({ runtime, busy, onAction }) { const running = runtime.state === 'running' return ( ) } function RuntimeTable({ runtimes, busy, onAction }) { return ( 环境状态ProfileCDP操作 {runtimes.map(runtime => ( {runtime.name}{runtime.status} {runtime.profile} {runtime.endpoint} ))}
) } function RuntimeCards({ runtimes, busy, onAction }) { return {runtimes.map(runtime => {runtime.name}{runtime.status}{runtime.profile})} } export function BrowserList() { const dataProvider = useDataProvider() const [name, setName] = useState('') const [seed, setSeed] = useState('1000') const [busy, setBusy] = useState('') const [localError, setLocalError] = useState('') const { data: runtimes = [], error, isPending, refetch } = useGetList('browsers', {}, { refetchInterval: 3000 }) useEffect(() => { document.title = 'CreatorHub · 运行环境' }, []) async function createRuntime(event) { event.preventDefault() setBusy('create') setLocalError('') try { await dataProvider.create('browsers', { data: { name, seed: Number(seed) } }) setName('') await refetch() } catch (reason) { setLocalError(reason.message) } finally { setBusy('') } } async function act(runtimeName, action) { if (action === 'recycle' && !window.confirm(`回收 ${runtimeName}?Profile 数据卷将保留。`)) return setBusy(runtimeName) setLocalError('') try { await dataProvider.browserAction(runtimeName, action) await refetch() } catch (reason) { setLocalError(reason.message) } finally { setBusy('') } } const message = localError || error?.message return ( <> 运行环境启动、停止并回收隔离的浏览器 Profile 环境名称 setName(event.target.value)} placeholder="例如:account-a" /> Fingerprint Seed setSeed(event.target.value)} /> {message ? { setLocalError(''); refetch() }}>重试} sx={{ mb: 2.5 }}>{message} : null} {isPending ? : null} {!isPending && runtimes.length === 0 ? 暂无运行环境,创建第一个隔离 Profile。 : null} {!isPending && runtimes.length > 0 ? <> : null} Docker socket 仅由受限网关访问 ) }