|
|
@@ -8,6 +8,7 @@ import {
|
|
|
clearTestResult
|
|
|
} from '../state/serverConfigSlice';
|
|
|
import { ServerConfig } from '../types';
|
|
|
+import { DEFAULT_SERVER_CONFIG } from '../services/ConfigService';
|
|
|
|
|
|
interface ServerConfigModalProps {
|
|
|
open: boolean;
|
|
|
@@ -30,14 +31,16 @@ const ServerConfigModal: React.FC<ServerConfigModalProps> = ({
|
|
|
useEffect(() => {
|
|
|
if (open && initialConfig) {
|
|
|
form.setFieldsValue({
|
|
|
- apiUrl: initialConfig.apiBaseUrl,
|
|
|
- mqttUrl: initialConfig.mqttBrokerUrl,
|
|
|
+ ip: initialConfig.ip,
|
|
|
+ apiPort: initialConfig.apiPort,
|
|
|
+ mqttPort: initialConfig.mqttPort,
|
|
|
});
|
|
|
} else if (open) {
|
|
|
// 默认值
|
|
|
form.setFieldsValue({
|
|
|
- apiUrl: 'http://127.0.0.1:8080',
|
|
|
- mqttUrl: 'ws://127.0.0.1:8083/mqtt',
|
|
|
+ ip: DEFAULT_SERVER_CONFIG.ip,
|
|
|
+ apiPort: DEFAULT_SERVER_CONFIG.apiPort,
|
|
|
+ mqttPort: DEFAULT_SERVER_CONFIG.mqttPort,
|
|
|
});
|
|
|
}
|
|
|
}, [open, initialConfig, form]);
|
|
|
@@ -48,7 +51,11 @@ const ServerConfigModal: React.FC<ServerConfigModalProps> = ({
|
|
|
const values = await form.validateFields();
|
|
|
dispatch(clearTestResult());
|
|
|
|
|
|
- const result = await dispatch(testConnectionThunk(values.apiUrl)).unwrap();
|
|
|
+ // 传递 IP 和端口
|
|
|
+ const result = await dispatch(testConnectionThunk({
|
|
|
+ ip: values.ip,
|
|
|
+ apiPort: parseInt(values.apiPort)
|
|
|
+ })).unwrap();
|
|
|
dispatch(setTestResult(result));
|
|
|
} catch (error) {
|
|
|
// 表单验证失败
|
|
|
@@ -61,9 +68,9 @@ const ServerConfigModal: React.FC<ServerConfigModalProps> = ({
|
|
|
const values = await form.validateFields();
|
|
|
|
|
|
const config: ServerConfig = {
|
|
|
- apiBaseUrl: values.apiUrl,
|
|
|
- mqttBrokerUrl: values.mqttUrl,
|
|
|
- name: '用户配置',
|
|
|
+ ip: values.ip,
|
|
|
+ apiPort: parseInt(values.apiPort),
|
|
|
+ mqttPort: parseInt(values.mqttPort),
|
|
|
};
|
|
|
|
|
|
await dispatch(saveAndApplyConfig(config)).unwrap();
|
|
|
@@ -75,37 +82,33 @@ const ServerConfigModal: React.FC<ServerConfigModalProps> = ({
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- // URL 验证规则
|
|
|
- const urlValidator = (rule: any, value: string) => {
|
|
|
+ // IP 地址验证规则
|
|
|
+ const ipValidator = (rule: any, value: string) => {
|
|
|
if (!value || value.trim() === '') {
|
|
|
- return Promise.reject('地址不能为空');
|
|
|
+ return Promise.reject('IP 地址不能为空');
|
|
|
}
|
|
|
|
|
|
- try {
|
|
|
- const url = new URL(value);
|
|
|
- if (!['http:', 'https:'].includes(url.protocol)) {
|
|
|
- return Promise.reject('只支持 HTTP 和 HTTPS 协议');
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- return Promise.reject('URL 格式不正确');
|
|
|
+ const ipPattern = /^(\d{1,3}\.){3}\d{1,3}$/;
|
|
|
+ if (!ipPattern.test(value)) {
|
|
|
+ return Promise.reject('IP 地址格式不正确');
|
|
|
+ }
|
|
|
+
|
|
|
+ const parts = value.split('.');
|
|
|
+ if (parts.some(part => parseInt(part) > 255)) {
|
|
|
+ return Promise.reject('IP 地址格式不正确');
|
|
|
}
|
|
|
|
|
|
return Promise.resolve();
|
|
|
};
|
|
|
|
|
|
- // MQTT URL 验证规则
|
|
|
- const mqttUrlValidator = (rule: any, value: string) => {
|
|
|
- if (!value || value.trim() === '') {
|
|
|
- return Promise.reject('MQTT 地址不能为空');
|
|
|
+ // 端口验证规则
|
|
|
+ const portValidator = (rule: any, value: number) => {
|
|
|
+ if (!value) {
|
|
|
+ return Promise.reject('端口不能为空');
|
|
|
}
|
|
|
|
|
|
- try {
|
|
|
- const url = new URL(value);
|
|
|
- if (!['ws:', 'wss:'].includes(url.protocol)) {
|
|
|
- return Promise.reject('只支持 WS 和 WSS 协议');
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- return Promise.reject('MQTT URL 格式不正确');
|
|
|
+ if (value < 1 || value > 65535) {
|
|
|
+ return Promise.reject('端口范围为 1-65535');
|
|
|
}
|
|
|
|
|
|
return Promise.resolve();
|
|
|
@@ -147,25 +150,30 @@ const ServerConfigModal: React.FC<ServerConfigModalProps> = ({
|
|
|
|
|
|
<Form form={form} layout="vertical">
|
|
|
<Form.Item
|
|
|
- label="API 服务器地址"
|
|
|
- name="apiUrl"
|
|
|
- rules={[{ validator: urlValidator }]}
|
|
|
- tooltip="后端 API 服务器的完整地址"
|
|
|
+ label="服务器 IP 地址"
|
|
|
+ name="ip"
|
|
|
+ rules={[{ validator: ipValidator }]}
|
|
|
+ tooltip="后端服务器的 IP 地址"
|
|
|
+ >
|
|
|
+ <Input placeholder="192.168.1.100" />
|
|
|
+ </Form.Item>
|
|
|
+
|
|
|
+ <Form.Item
|
|
|
+ label="API 服务端口"
|
|
|
+ name="apiPort"
|
|
|
+ rules={[{ validator: portValidator }]}
|
|
|
+ tooltip="后端 API 服务的端口号"
|
|
|
>
|
|
|
- <Input
|
|
|
- placeholder="http://192.168.1.100:8080"
|
|
|
- />
|
|
|
+ <Input type="number" placeholder="8080" />
|
|
|
</Form.Item>
|
|
|
|
|
|
<Form.Item
|
|
|
- label="MQTT 服务器地址"
|
|
|
- name="mqttUrl"
|
|
|
- rules={[{ validator: mqttUrlValidator }]}
|
|
|
- tooltip="MQTT 消息服务器的 WebSocket 地址"
|
|
|
+ label="MQTT 服务端口"
|
|
|
+ name="mqttPort"
|
|
|
+ rules={[{ validator: portValidator }]}
|
|
|
+ tooltip="MQTT 消息服务的端口号"
|
|
|
>
|
|
|
- <Input
|
|
|
- placeholder="ws://192.168.1.100:8083/mqtt"
|
|
|
- />
|
|
|
+ <Input type="number" placeholder="8083" />
|
|
|
</Form.Item>
|
|
|
</Form>
|
|
|
|