فهرست منبع

feat(1.30.4 -> 1.31.0): IP 地址管理功能模块,核心实现可用 IP 列表展示→用户交互选择→配置本地保存→下次启动自动加载的完整流程,减少用户重复手动输入 / 选择 IP 的操作,确保模块启动后可快速使用指定 IP 访问服务器

szy 2 هفته پیش
والد
کامیت
fa8da226cd

+ 24 - 0
src/API/system/network.ts

@@ -0,0 +1,24 @@
+import axiosInstance from '../interceptor';
+import { ServerConfig } from '../../features/serverConfig/types';
+export interface NetInfo {
+  name: string;
+  ipv4: string;
+  ipv6: string;
+  flags: string;
+  enabled: boolean;
+  type: string;
+  state: string;
+  connection: string;
+}
+export interface NetInfoResponse {
+  code: string;
+  description: string;
+  solution: string;
+  data: NetInfo[];
+}
+const getNetInfo = async (): Promise<NetInfoResponse> => {
+  const res = await axiosInstance.get('/pub/net_info');
+  return res.data;
+};
+
+export { getNetInfo };

+ 2 - 2
src/features/serverConfig/state/serverConfigSlice.ts

@@ -163,7 +163,7 @@ const serverConfigSlice = createSlice({
         state.loading = false;
         state.error = action.error.message || '加载配置失败';
       })
-      
+
       // 测试连接
       .addCase(testConnectionThunk.pending, (state) => {
         state.testing = true;
@@ -180,7 +180,7 @@ const serverConfigSlice = createSlice({
           message: action.error.message || '测试失败',
         };
       })
-      
+
       // 保存并应用配置
       .addCase(saveAndApplyConfig.pending, (state) => {
         state.loading = true;

+ 5 - 0
src/pages/system/SettingsModal/config.tsx

@@ -207,6 +207,11 @@ export const settingsConfig: SettingsCategory[] = [
         title: '标记映射',
         component: Network.TagMapping,
       },
+      {
+        id: 'ip',
+        title: 'IP',
+        component: Network.Ip,
+      },
       {
         id: 'network_test',
         title: '测试',

+ 6 - 0
src/pages/system/SettingsModal/sections/Network/index.tsx

@@ -3,6 +3,7 @@
  */
 import React from 'react';
 import PlaceholderSection from '../PlaceholderSection';
+export { default as Ip } from './ip';
 
 // 管接
 export const Connection: React.FC = () => (
@@ -19,6 +20,11 @@ export const TagMapping: React.FC = () => (
   <PlaceholderSection title="标记映射" />
 );
 
+// // IP
+// export const Ip: React.FC = () => (
+//   <PlaceholderSection title="IP" />
+// );
+
 // 测试
 export const NetworkTest: React.FC = () => (
   <PlaceholderSection title="测试" />

+ 123 - 0
src/pages/system/SettingsModal/sections/Network/ip.tsx

@@ -0,0 +1,123 @@
+import React, { useEffect, useState } from 'react';
+import { Radio, Card, Button, Typography, Space, Tag } from 'antd';
+import { InfoCircleOutlined } from '@ant-design/icons';
+import ConfigService from '../../../../../features/serverConfig/services/ConfigService';
+import { getNetInfo, NetInfo } from '../../../../../API/system/network';
+import { SPACING } from '../../constants';
+
+const Ip: React.FC = () => {
+  const [netList, setNetList] = useState<NetInfo[]>([]);
+  const [serverInfo, setServerInfo] = useState({});
+
+  const getNetInfoData = async (): Promise<void> => {
+    const res = getNetInfo();
+    console.log('res', res);
+    setNetList([
+      {
+        name: 'eth0',
+        ipv4: '192.168.100.100',
+        ipv6: '',
+        flags: 'up|broadcast|multicast',
+        enabled: true,
+        type: 'ethernet',
+        state: 'connected',
+        connection: '(externally)  eth0',
+      },
+      {
+        name: 'eth0',
+        ipv4: '127.0.0.1',
+        ipv6: '',
+        flags: 'up|broadcast|multicast',
+        enabled: true,
+        type: 'ethernet',
+        state: 'connected',
+        connection: '(externally)  eth0',
+      },
+      {
+        name: 'eth1',
+        ipv4: '192.168.11.252',
+        ipv6: '',
+        flags: 'up|broadcast|multicast',
+        enabled: true,
+        type: 'ethernet',
+        state: 'connected',
+        connection: '(externally)  eth1',
+      },
+      {
+        name: 'wlP4p65s0',
+        ipv4: '192.168.110.13',
+        ipv6: 'fe80::a7d6:8818:341c:5656',
+        flags: 'up|broadcast|multicast|running',
+        enabled: true,
+        type: 'wifi',
+        state: 'connected',
+        connection: 'zskkxk_5G',
+      },
+    ]);
+  };
+
+  const { Text } = Typography;
+
+  const radioStyle: React.CSSProperties = {
+    display: 'flex',
+    flexDirection: 'column',
+    gap: 8,
+  };
+
+  const onChange = (e) => {
+    setServerInfo((serverInfo) => ({
+      ...serverInfo,
+      ip: e.target.value,
+    }));
+  };
+
+  const getServerInfo = async () => {
+    const serveRes = await ConfigService.getServerConfig();
+    setServerInfo(serveRes);
+  };
+
+  const saveServerInfo = () => {
+    console.log('serverInfo==========================>', serverInfo);
+    ConfigService.saveServerConfig(serverInfo);
+  };
+
+  useEffect(() => {
+    getServerInfo();
+    getNetInfoData();
+  }, []);
+
+  return (
+    <div style={{ padding: SPACING.LG }}>
+      <Space direction="vertical" style={{ display: 'flex' }}>
+        {serverInfo.ip}
+        <Card title="IP地址配置" variant="borderless">
+          <Radio.Group
+            style={radioStyle}
+            onChange={onChange}
+            value={serverInfo.ip}
+          >
+            {netList.map((k) => (
+              <Radio key={k.ipv4} value={k.ipv4}>
+                {k.ipv4}{' '}
+                {k.type === 'wifi' && (
+                  <Tag bordered={false}>{k.connection}</Tag>
+                )}
+              </Radio>
+            ))}
+          </Radio.Group>
+        </Card>
+        <Text type="secondary">
+          <InfoCircleOutlined style={{ marginRight: 6 }} />
+          选择IP地址,保存后需要重启软件才能生效
+        </Text>
+        <div>
+          <Button type="primary" onClick={saveServerInfo}>
+            保存
+          </Button>
+        </div>
+      </Space>
+    </div>
+  );
+};
+
+export default Ip;