119 lines
3.4 KiB
TypeScript
119 lines
3.4 KiB
TypeScript
import { useState, ReactNode } from 'react';
|
||
import { NodeData, Settings } from '../types/graph';
|
||
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();
|
||
};
|
||
|
||
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 || ''}
|
||
onChange={(e) => handleInputChange('privateKey', e.target.value)}
|
||
readOnly
|
||
/>
|
||
<button className="btn-interect">重新生成</button>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<div className="form-group">
|
||
<label>侦听端口</label>
|
||
<input
|
||
type="number"
|
||
value={formData.listenPort || ''}
|
||
onChange={(e) => handleInputChange('listenPort', e.target.value)}
|
||
placeholder="例如: 51820"
|
||
/>
|
||
</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"
|
||
/>
|
||
</div>
|
||
|
||
<div className="form-group">
|
||
<label>持久保活 (可选)</label>
|
||
<input
|
||
type="number"
|
||
value={formData.persistentKeepalive || ''}
|
||
onChange={(e) => handleInputChange('persistentKeepalive', e.target.value)}
|
||
placeholder="秒数"
|
||
/>
|
||
</div>
|
||
|
||
<div className="editor-actions">
|
||
<button className="btn-save" onClick={handleSave}>保存</button>
|
||
<button className="btn-cancel" onClick={onClose}>取消</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|