171 lines
4.4 KiB
TypeScript
171 lines
4.4 KiB
TypeScript
import React, { useState, useEffect } from 'react'
|
||
import { Modal, Form, Input, Button, Alert, Space } from 'antd'
|
||
import { useSelector } from 'react-redux'
|
||
import type { RootState } from '../../store/store'
|
||
|
||
interface ConnectDialogProps {
|
||
visible: boolean
|
||
onConnect: (url: string) => void
|
||
onCancel: () => void
|
||
}
|
||
|
||
/**
|
||
* 连接服务器对话框
|
||
*/
|
||
const ConnectDialog: React.FC<ConnectDialogProps> = ({
|
||
visible,
|
||
onConnect,
|
||
onCancel
|
||
}) => {
|
||
const [form] = Form.useForm()
|
||
const [loading, setLoading] = useState(false)
|
||
const { status: connectionStatus, serverUrl } = useSelector((state: RootState) => state.connection)
|
||
|
||
// 预设服务器地址选项
|
||
const presetServers = [
|
||
'ws://localhost:3001',
|
||
'ws://127.0.0.1:3001',
|
||
'ws://192.168.1.100:3001', // 示例局域网地址
|
||
]
|
||
|
||
useEffect(() => {
|
||
if (visible) {
|
||
// 如果已有服务器地址,使用它作为默认值
|
||
if (serverUrl) {
|
||
form.setFieldValue('serverUrl', serverUrl)
|
||
} else {
|
||
form.setFieldValue('serverUrl', 'ws://localhost:3001')
|
||
}
|
||
}
|
||
}, [visible, serverUrl, form])
|
||
|
||
useEffect(() => {
|
||
if (connectionStatus === 'connected') {
|
||
setLoading(false)
|
||
} else if (connectionStatus === 'error') {
|
||
setLoading(false)
|
||
}
|
||
}, [connectionStatus])
|
||
|
||
const handleConnect = async () => {
|
||
try {
|
||
const values = await form.validateFields()
|
||
setLoading(true)
|
||
onConnect(values.serverUrl)
|
||
} catch (error) {
|
||
console.error('表单验证失败:', error)
|
||
}
|
||
}
|
||
|
||
const handlePresetSelect = (url: string) => {
|
||
form.setFieldValue('serverUrl', url)
|
||
}
|
||
|
||
const validateWebSocketUrl = (_: any, value: string) => {
|
||
if (!value) {
|
||
return Promise.reject(new Error('请输入服务器地址'))
|
||
}
|
||
|
||
if (!value.startsWith('ws://') && !value.startsWith('wss://')) {
|
||
return Promise.reject(new Error('地址必须以 ws:// 或 wss:// 开头'))
|
||
}
|
||
|
||
try {
|
||
new URL(value)
|
||
return Promise.resolve()
|
||
} catch {
|
||
return Promise.reject(new Error('请输入有效的WebSocket地址'))
|
||
}
|
||
}
|
||
|
||
return (
|
||
<Modal
|
||
title="连接到远程控制服务器"
|
||
open={visible}
|
||
onCancel={onCancel}
|
||
width={500}
|
||
footer={[
|
||
<Button key="cancel" onClick={onCancel}>
|
||
取消
|
||
</Button>,
|
||
<Button
|
||
key="connect"
|
||
type="primary"
|
||
loading={loading}
|
||
onClick={handleConnect}
|
||
>
|
||
{loading ? '连接中...' : '连接'}
|
||
</Button>,
|
||
]}
|
||
maskClosable={false}
|
||
>
|
||
<Form
|
||
form={form}
|
||
layout="vertical"
|
||
initialValues={{
|
||
serverUrl: 'ws://localhost:3001'
|
||
}}
|
||
>
|
||
<Form.Item
|
||
label="服务器地址"
|
||
name="serverUrl"
|
||
rules={[
|
||
{ validator: validateWebSocketUrl }
|
||
]}
|
||
help="输入WebSocket服务器地址,例如: ws://localhost:3001"
|
||
>
|
||
<Input
|
||
placeholder="ws://localhost:3001"
|
||
size="large"
|
||
autoFocus
|
||
onPressEnter={handleConnect}
|
||
/>
|
||
</Form.Item>
|
||
|
||
<div style={{ marginBottom: '16px' }}>
|
||
<div style={{ marginBottom: '8px', color: '#666', fontSize: '14px' }}>
|
||
常用地址:
|
||
</div>
|
||
<Space wrap>
|
||
{presetServers.map((url) => (
|
||
<Button
|
||
key={url}
|
||
size="small"
|
||
type="dashed"
|
||
onClick={() => handlePresetSelect(url)}
|
||
>
|
||
{url}
|
||
</Button>
|
||
))}
|
||
</Space>
|
||
</div>
|
||
|
||
{connectionStatus === 'error' && (
|
||
<Alert
|
||
message="连接失败"
|
||
description="无法连接到服务器,请检查地址是否正确,服务器是否运行正常"
|
||
type="error"
|
||
showIcon
|
||
style={{ marginBottom: '16px' }}
|
||
/>
|
||
)}
|
||
|
||
<Alert
|
||
message="使用说明"
|
||
description={
|
||
<div>
|
||
<p>1. 确保远程控制服务器已启动</p>
|
||
<p>2. 如果服务器在本机,使用 localhost 或 127.0.0.1</p>
|
||
<p>3. 如果服务器在局域网,使用服务器的IP地址</p>
|
||
<p>4. 确保防火墙已开放相应端口</p>
|
||
</div>
|
||
}
|
||
type="info"
|
||
showIcon
|
||
/>
|
||
</Form>
|
||
</Modal>
|
||
)
|
||
}
|
||
|
||
export default ConnectDialog
|