182 lines
5.2 KiB
TypeScript
182 lines
5.2 KiB
TypeScript
import { useState, ReactNode } from 'react';
|
||
import { NodeData, Settings } from '../types/graph';
|
||
import { generateWireGuardPrivateKey } from '../utils/wireguardConfig'
|
||
import './NodeEditor.css';
|
||
|
||
|
||
|
||
interface NodeEditorProps {
|
||
node: NodeData;
|
||
settings: Settings;
|
||
onUpdate: (data: NodeData) => void;
|
||
onClose: () => void;
|
||
}
|
||
|
||
export default function NodeEditor({
|
||
node,
|
||
settings,
|
||
onUpdate,
|
||
onClose
|
||
}: NodeEditorProps): ReactNode {
|
||
const [formData, setFormData] = useState<NodeData>(node);
|
||
const [errors, setErrors] = useState<string[]>([]);
|
||
|
||
const handleInputChange = (field: keyof NodeData, value: string): void => {
|
||
setFormData(prev => ({
|
||
...prev,
|
||
[field]: value
|
||
}));
|
||
};
|
||
|
||
const handleSave = (): void => {
|
||
// const validation = validateNodeConfig(formData);
|
||
// if (!validation.isValid) {
|
||
// setErrors(validation.errors);
|
||
// return;
|
||
// }
|
||
|
||
// setErrors([]);
|
||
// onUpdate(formData);
|
||
// onClose();
|
||
};
|
||
|
||
const handleGenerateKey = (): void => {
|
||
handleInputChange('privateKey', generateWireGuardPrivateKey())
|
||
}
|
||
|
||
return (
|
||
<div className="node-editor-overlay">
|
||
<div className="node-editor">
|
||
<div className="editor-header">
|
||
<h2>编辑节点: {formData.label || '新节点'}</h2>
|
||
<button className="close-btn" onClick={onClose}>×</button>
|
||
</div>
|
||
|
||
{errors.length > 0 && (
|
||
<div className="error-box">
|
||
{errors.map((error, idx) => (
|
||
<p key={idx} className="error-message">• {error}</p>
|
||
))}
|
||
</div>
|
||
)}
|
||
|
||
<div className="form-group">
|
||
<label>节点名称</label>
|
||
<input
|
||
type="text"
|
||
value={formData.label || ''}
|
||
onChange={(e) => handleInputChange('label', e.target.value)}
|
||
placeholder="例如: Node-A"
|
||
/>
|
||
</div>
|
||
|
||
<div className="form-group">
|
||
<label>私钥</label>
|
||
<div className="item-group">
|
||
<input
|
||
value={formData.privateKey || ''}
|
||
readOnly
|
||
/>
|
||
<button className="btn-interect" onClick={handleGenerateKey}>重新生成</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="form-group">
|
||
<label>主机ID</label>
|
||
<input
|
||
type="number"
|
||
min="0"
|
||
max="255"
|
||
step="1"
|
||
value={formData.hostId}
|
||
onChange={(e) => handleInputChange('hostId', e.target.value)}
|
||
placeholder="同一子网ID下主机ID不能重复,不得超过255"
|
||
/>
|
||
</div>
|
||
|
||
<div className="form-group">
|
||
<label>子网ID</label>
|
||
<input
|
||
type="number"
|
||
min="0"
|
||
max="255"
|
||
step="1"
|
||
value={formData.groupId}
|
||
onChange={(e) => handleInputChange('groupId', e.target.value)}
|
||
placeholder="不得超过255"
|
||
/>
|
||
</div>
|
||
|
||
{/* host options */}
|
||
|
||
<div className="form-group">
|
||
<label>PostUp (可选)</label>
|
||
<input
|
||
type="text"
|
||
value={formData.postUp || ''}
|
||
onChange={(e) => handleInputChange('postUp', e.target.value)}
|
||
/>
|
||
</div>
|
||
|
||
<div className="form-group">
|
||
<label>PostDown (可选)</label>
|
||
<input
|
||
type="text"
|
||
value={formData.postDown || ''}
|
||
onChange={(e) => handleInputChange('postDown', e.target.value)}
|
||
/>
|
||
</div>
|
||
|
||
<div className="form-group">
|
||
<label>mtu (可选)</label>
|
||
<input
|
||
type="number"
|
||
min="1"
|
||
step="1"
|
||
value={formData.mtu || ''}
|
||
onChange={(e) => handleInputChange('mtu', e.target.value)}
|
||
placeholder={settings.mtu ? `默认值:${settings.mtu}` : ''}
|
||
/>
|
||
</div>
|
||
|
||
<div className="form-group">
|
||
<label>侦听端口 (可选)</label>
|
||
<input
|
||
type="number"
|
||
min="1024"
|
||
max="49151"
|
||
step="1"
|
||
value={formData.listenPort || ''}
|
||
onChange={(e) => handleInputChange('listenPort', e.target.value)}
|
||
placeholder={`默认值:${settings.listenPort}`}
|
||
/>
|
||
</div>
|
||
|
||
<div className="form-group">
|
||
<label>DNS服务器 (可选)</label>
|
||
<input
|
||
type="text"
|
||
value={formData.dnsServers || ''}
|
||
onChange={(e) => handleInputChange('dnsServers', e.target.value)}
|
||
placeholder="例如: 8.8.8.8,1.1.1.1"
|
||
/>
|
||
</div>
|
||
|
||
<div className="form-group">
|
||
<label>备注 (可选)</label>
|
||
<textarea
|
||
rows={3}
|
||
value={formData.notes || ''}
|
||
onChange={(e) => handleInputChange('notes', e.target.value)}
|
||
/>
|
||
</div>
|
||
|
||
<div className="editor-actions">
|
||
<button className="btn-save" onClick={handleSave}>保存</button>
|
||
<button className="btn-cancel" onClick={onClose}>取消</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|