import { useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom' import { useRelayNodeStore } from '../stores/relayNodeStore' import { useConfigStore } from '../stores/configStore' import { useAuthStore } from '../stores/authStore' export default function SettingsPage() { const navigate = useNavigate() const { nodes, loading, fetchNodes, addNode, removeNode, reportPing } = useRelayNodeStore() const { config, customServerUrl, setCustomServer, clearCustomServer } = useConfigStore() const { logout } = useAuthStore() const [newName, setNewName] = useState('') const [newUrl, setNewUrl] = useState('') const [newRegion, setNewRegion] = useState('') const [adding, setAdding] = useState(false) const [addError, setAddError] = useState('') const [pinging, setPinging] = useState(null) const [showServerChange, setShowServerChange] = useState(false) const [newServerUrl, setNewServerUrl] = useState('') const [serverError, setServerError] = useState('') const [changingServer, setChangingServer] = useState(false) useEffect(() => { fetchNodes() }, []) const handleAdd = async (e: React.FormEvent) => { e.preventDefault() setAddError('') setAdding(true) try { await addNode(newName, newUrl, newRegion || undefined) setNewName('') setNewUrl('') setNewRegion('') } catch (e: any) { setAddError(String(e)) } finally { setAdding(false) } } const handlePing = async (id: string, url: string) => { setPinging(id) try { const start = performance.now() await fetch(`${url}/ping`, { signal: AbortSignal.timeout(4000) }).catch(() => {}) const rtt = Math.round(performance.now() - start) await reportPing(id, rtt) } finally { setPinging(null) } } return (

设置

管理应用配置

{/* Server config */}

服务器连接

当前连接的服务器信息

{config?.server_name || 'FunMC Server'}

{config?.server_url || '未配置'}

已连接
{customServerUrl && (

使用自定义服务器

)}
{showServerChange ? (
setNewServerUrl(e.target.value)} placeholder="输入新的服务器地址" className="input-field" /> {serverError && (

{serverError}

)}
) : (
{customServerUrl && ( )}
)}
{/* Relay nodes */}

中继服务器节点

支持多节点,P2P 穿透失败时自动选择延迟最低的节点进行流量中继。

{loading ? (

加载中...

) : nodes.length === 0 ? (

暂无节点

) : (
{nodes.map((node) => (
{node.name} {node.region && node.region !== 'auto' && ( {node.region} )} {node.priority > 0 && ( 主节点 )}

{node.url}

{node.last_ping_ms != null && ( {node.last_ping_ms} ms )}
))}
)} {/* Add form */}

添加节点

setNewName(e.target.value)} required /> setNewUrl(e.target.value)} type="url" required /> setNewRegion(e.target.value)} />
{addError &&

{addError}

}
{/* About */}

关于

版本 0.1.0
官网 fc.funmc.cn
使用文档 fc.funmc.cn/docs
魔幻方开发

© 2024 魔幻方. All rights reserved.

) }