From e3fed713ffc95ae3622c59ee67b2152a7309932a Mon Sep 17 00:00:00 2001 From: fengfeng Date: Sat, 31 Jan 2026 19:55:33 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=85=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 9 +- src/components/ConfigViewer.css | 219 -------------------------------- src/components/ConfigViewer.tsx | 121 ------------------ src/types/graph.ts | 23 +++- 4 files changed, 23 insertions(+), 349 deletions(-) delete mode 100644 src/components/ConfigViewer.css delete mode 100644 src/components/ConfigViewer.tsx diff --git a/src/App.tsx b/src/App.tsx index f048db5..d09de87 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -20,7 +20,6 @@ import '@xyflow/react/dist/style.css'; import { AppNode, AppEdge, NodeData } from './types/graph'; import CustomNode from './components/CustomNode'; import NodeEditor from './components/NodeEditor'; -import ConfigViewer from './components/ConfigViewer'; import Toggle from "./components/Toggle" import './App.css'; @@ -147,8 +146,8 @@ function FlowContent(): ReactNode { ➕ 添加节点 - @@ -162,13 +161,13 @@ function FlowContent(): ReactNode { /> )} - {showConfigViewer && ( + {/* {showConfigViewer && ( setShowConfigViewer(false)} /> - )} + )} */} ); } diff --git a/src/components/ConfigViewer.css b/src/components/ConfigViewer.css deleted file mode 100644 index f495c8e..0000000 --- a/src/components/ConfigViewer.css +++ /dev/null @@ -1,219 +0,0 @@ -.config-viewer-overlay { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: rgba(0, 0, 0, 0.5); - display: flex; - align-items: center; - justify-content: center; - z-index: 1001; -} - -.config-viewer { - background: white; - border-radius: 8px; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); - max-width: 900px; - width: 95%; - max-height: 85vh; - display: flex; - flex-direction: column; - overflow: hidden; -} - -.viewer-header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 20px; - border-bottom: 1px solid #eee; - flex-shrink: 0; -} - -.viewer-header h2 { - margin: 0; - font-size: 18px; - color: #333; -} - -.close-btn { - background: none; - border: none; - font-size: 24px; - cursor: pointer; - color: #999; - padding: 0; - width: 30px; - height: 30px; - display: flex; - align-items: center; - justify-content: center; -} - -.close-btn:hover { - color: #333; -} - -.viewer-content { - display: flex; - gap: 20px; - flex: 1; - overflow: hidden; - padding: 20px; -} - -.config-list { - min-width: 200px; - max-width: 250px; - border-right: 1px solid #eee; - padding-right: 20px; - overflow-y: auto; -} - -.config-list h3 { - margin: 0 0 10px 0; - font-size: 14px; - color: #333; -} - -.config-item { - display: flex; - justify-content: space-between; - align-items: center; - padding: 8px; - margin-bottom: 8px; - background: #f5f5f5; - border-radius: 4px; - font-size: 13px; - gap: 8px; -} - -.config-item span { - flex: 1; - word-break: break-all; -} - -.download-btn { - background: none; - border: none; - cursor: pointer; - font-size: 16px; - padding: 0; - flex-shrink: 0; -} - -.config-preview { - flex: 1; - display: flex; - flex-direction: column; - min-width: 400px; - overflow: hidden; -} - -.preview-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 10px; -} - -.preview-header h3 { - margin: 0; - font-size: 14px; - color: #333; -} - -.copy-btn { - padding: 6px 12px; - background: #1677ff; - color: white; - border: none; - border-radius: 4px; - cursor: pointer; - font-size: 12px; - font-weight: 500; - transition: background 0.3s; -} - -.copy-btn:hover { - background: #0b66d4; -} - -.config-text { - flex: 1; - background: #f5f5f5; - border: 1px solid #ddd; - border-radius: 4px; - padding: 12px; - overflow: auto; - font-size: 12px; - line-height: 1.5; - color: #333; - margin: 0; - font-family: 'Courier New', monospace; -} - -.viewer-actions { - display: flex; - gap: 10px; - padding: 20px; - border-top: 1px solid #eee; - flex-shrink: 0; -} - -.btn-download-all, -.btn-close { - padding: 10px 16px; - border: none; - border-radius: 4px; - font-size: 14px; - font-weight: 500; - cursor: pointer; - transition: all 0.3s ease; -} - -.btn-download-all { - flex: 1; - background: #52c41a; - color: white; -} - -.btn-download-all:hover:not(:disabled) { - background: #389e0d; - box-shadow: 0 2px 8px rgba(82, 196, 26, 0.3); -} - -.btn-download-all:disabled { - background: #ccc; - cursor: not-allowed; -} - -.btn-close { - flex: 1; - background: #f5f5f5; - color: #333; -} - -.btn-close:hover { - background: #e6e6e6; -} - -@media (max-width: 768px) { - .viewer-content { - flex-direction: column; - } - - .config-list { - max-width: none; - border-right: none; - border-bottom: 1px solid #eee; - padding-right: 0; - padding-bottom: 15px; - } - - .config-preview { - min-width: auto; - } -} diff --git a/src/components/ConfigViewer.tsx b/src/components/ConfigViewer.tsx deleted file mode 100644 index 2fdeed4..0000000 --- a/src/components/ConfigViewer.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import { ReactNode, useState } from 'react'; -import { generateAllConfigs, downloadConfig } from '../utils/wireguardConfig'; -import {AppNode, AppEdge} from '../types/graph'; -import './ConfigViewer.css'; - -interface ConfigViewerProps { - nodes: AppNode[]; - edges: AppEdge[]; - onClose: () => void; -} - -interface ConfigItem { - name: string; - config: string; -} - -interface Configs { - [key: string]: ConfigItem; -} - -export default function ConfigViewer({ - nodes, - edges, - onClose -}: ConfigViewerProps): ReactNode { - const configs: Configs = generateAllConfigs(nodes, edges); - const configIds = Object.keys(configs); - const [selectedId, setSelectedId] = useState(configIds[0] || null); - - const handleDownload = (nodeId: string): void => { - const config = configs[nodeId]; - if (config) { - downloadConfig(nodeId, config.name, config.config); - } - }; - - const handleDownloadAll = (): void => { - Object.keys(configs).forEach(nodeId => { - const config = configs[nodeId]; - if (config) { - setTimeout(() => { - downloadConfig(nodeId, config.name, config.config); - }, 100); - } - }); - }; - - if (!selectedId || !configs[selectedId]) { - return ( -
-
-
-

WireGuard配置

- -
-

- 没有可用的配置。请确保节点有完整的WireGuard配置信息。 -

-
-
- ); - } - - const config = configs[selectedId]; - - return ( -
-
-
-

WireGuard配置查看器

- -
- -
-
-

节点配置列表

- {configIds.map(nodeId => ( -
- {configs[nodeId].name} - -
- ))} -
- -
-
-

{config.name} 的配置

- -
-
{config.config}
-
-
- -
- - -
-
-
- ); -} diff --git a/src/types/graph.ts b/src/types/graph.ts index 4aa095e..89af9d6 100644 --- a/src/types/graph.ts +++ b/src/types/graph.ts @@ -5,16 +5,31 @@ export type AppNode = Node; export type AppEdge = Edge; export type NodeData = { + // basic label: string; - ipAddress: string; - listenPort: string; + subnet: string; privateKey: string; publicKey: string; - endpoint?: string; - dnsServers?: string; + + // options + PostUp?: string; + PostDown?: string; persistentKeepalive?: string; + dnsServers?: string; + disallowSubnet?: string; + allowIPs?: string; + MTU?: number } export type EdgeData = { isTwoWayEdge: boolean +} + +export type Settings = { + v4SubNetPrefix: string; + v6SubNetPrefix: string; + listenPort: string; + + // global options + MTU?: number; } \ No newline at end of file