|
|
@@ -27,6 +27,7 @@ export default function RemoteServerControl() {
|
|
|
const [usePreConfigured, setUsePreConfigured] = useState(true);
|
|
|
const [preConfiguredServers, setPreConfiguredServers] = useState<PreConfiguredServer[]>([]);
|
|
|
const [selectedServerId, setSelectedServerId] = useState<string>('');
|
|
|
+ const [selectedPath, setSelectedPath] = useState<string>('/root/troov-asyncio');
|
|
|
const [serverConfig, setServerConfig] = useState<ServerConfig>({
|
|
|
host: '',
|
|
|
port: 22,
|
|
|
@@ -66,14 +67,20 @@ export default function RemoteServerControl() {
|
|
|
setConnecting(false);
|
|
|
return;
|
|
|
}
|
|
|
- response = await api.post('/api/remote/server/docker/status', { server_id: selectedServerId });
|
|
|
+ response = await api.post('/api/remote/server/docker/status', {
|
|
|
+ server_id: selectedServerId,
|
|
|
+ project_path: selectedPath
|
|
|
+ });
|
|
|
} else {
|
|
|
if (!serverConfig.host || !serverConfig.username) {
|
|
|
setConnectionError('请填写服务器地址和用户名');
|
|
|
setConnecting(false);
|
|
|
return;
|
|
|
}
|
|
|
- response = await api.post('/api/remote/docker/status', serverConfig);
|
|
|
+ response = await api.post('/api/remote/docker/status', {
|
|
|
+ ...serverConfig,
|
|
|
+ project_path: selectedPath
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
if (response.data.code === 0) {
|
|
|
@@ -144,53 +151,77 @@ export default function RemoteServerControl() {
|
|
|
|
|
|
{/* 卡片内容 */}
|
|
|
<div className="p-4 md:p-6 space-y-5">
|
|
|
- {usePreConfigured ? (
|
|
|
- <div>
|
|
|
- <label className="block text-xs font-bold text-slate-500 uppercase mb-2">选择目标服务器</label>
|
|
|
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
|
+ {usePreConfigured ? (
|
|
|
+ <div className="space-y-1">
|
|
|
+ <label className="block text-xs font-bold text-slate-500 uppercase mb-2">选择目标服务器</label>
|
|
|
+ <div className="relative">
|
|
|
+ <select
|
|
|
+ value={selectedServerId}
|
|
|
+ onChange={(e) => setSelectedServerId(e.target.value)}
|
|
|
+ className="w-full pl-4 pr-10 py-3 border border-slate-300 rounded-xl appearance-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none text-sm bg-white"
|
|
|
+ disabled={isConnected}
|
|
|
+ >
|
|
|
+ <option value="">-- 请选择服务器 --</option>
|
|
|
+ {preConfiguredServers.map((server) => (
|
|
|
+ <option key={server.id} value={server.id}>
|
|
|
+ {server.name} ({server.host})
|
|
|
+ </option>
|
|
|
+ ))}
|
|
|
+ </select>
|
|
|
+ <div className="absolute right-3 top-3.5 text-slate-400 pointer-events-none">
|
|
|
+ <Search size={16} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ ) : (
|
|
|
+ // 手动输入模式:移动端单列,桌面端双列
|
|
|
+ <>
|
|
|
+ <div className="space-y-1">
|
|
|
+ <label className="text-xs font-bold text-slate-500">IP 地址</label>
|
|
|
+ <input
|
|
|
+ type="text"
|
|
|
+ value={serverConfig.host}
|
|
|
+ onChange={(e) => setServerConfig({ ...serverConfig, host: e.target.value })}
|
|
|
+ placeholder="192.168.1.100"
|
|
|
+ className="w-full px-3 py-2.5 border border-slate-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 outline-none"
|
|
|
+ disabled={isConnected}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div className="space-y-1">
|
|
|
+ <label className="text-xs font-bold text-slate-500">端口</label>
|
|
|
+ <input
|
|
|
+ type="number"
|
|
|
+ value={serverConfig.port}
|
|
|
+ onChange={(e) => setServerConfig({ ...serverConfig, port: parseInt(e.target.value) || 22 })}
|
|
|
+ className="w-full px-3 py-2.5 border border-slate-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 outline-none"
|
|
|
+ disabled={isConnected}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+
|
|
|
+ <div className="space-y-1">
|
|
|
+ <label className="block text-xs font-bold text-slate-500 uppercase mb-2">项目路径</label>
|
|
|
<div className="relative">
|
|
|
<select
|
|
|
- value={selectedServerId}
|
|
|
- onChange={(e) => setSelectedServerId(e.target.value)}
|
|
|
+ value={selectedPath}
|
|
|
+ onChange={(e) => setSelectedPath(e.target.value)}
|
|
|
className="w-full pl-4 pr-10 py-3 border border-slate-300 rounded-xl appearance-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none text-sm bg-white"
|
|
|
disabled={isConnected}
|
|
|
>
|
|
|
- <option value="">-- 请选择服务器 --</option>
|
|
|
- {preConfiguredServers.map((server) => (
|
|
|
- <option key={server.id} value={server.id}>
|
|
|
- {server.name} ({server.host})
|
|
|
- </option>
|
|
|
- ))}
|
|
|
+ <option value="/root/troov-asyncio">默认项目 (/root/troov-asyncio)</option>
|
|
|
+ <option value="/root/germany_visa">德国签证 (/root/germany_visa)</option>
|
|
|
</select>
|
|
|
<div className="absolute right-3 top-3.5 text-slate-400 pointer-events-none">
|
|
|
- <Search size={16} />
|
|
|
+ <Settings size={16} />
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- ) : (
|
|
|
- // 手动输入模式:移动端单列,桌面端双列
|
|
|
- <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
|
- <div className="space-y-1">
|
|
|
- <label className="text-xs font-bold text-slate-500">IP 地址</label>
|
|
|
- <input
|
|
|
- type="text"
|
|
|
- value={serverConfig.host}
|
|
|
- onChange={(e) => setServerConfig({ ...serverConfig, host: e.target.value })}
|
|
|
- placeholder="192.168.1.100"
|
|
|
- className="w-full px-3 py-2.5 border border-slate-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 outline-none"
|
|
|
- disabled={isConnected}
|
|
|
- />
|
|
|
- </div>
|
|
|
- <div className="space-y-1">
|
|
|
- <label className="text-xs font-bold text-slate-500">端口</label>
|
|
|
- <input
|
|
|
- type="number"
|
|
|
- value={serverConfig.port}
|
|
|
- onChange={(e) => setServerConfig({ ...serverConfig, port: parseInt(e.target.value) || 22 })}
|
|
|
- className="w-full px-3 py-2.5 border border-slate-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 outline-none"
|
|
|
- disabled={isConnected}
|
|
|
- />
|
|
|
- </div>
|
|
|
- {/* 其他字段同理... */}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {!usePreConfigured && (
|
|
|
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4 pt-2 border-t border-slate-50">
|
|
|
<div className="space-y-1">
|
|
|
<label className="text-xs font-bold text-slate-500">用户名</label>
|
|
|
<input
|
|
|
@@ -306,18 +337,21 @@ export default function RemoteServerControl() {
|
|
|
<DockerControl
|
|
|
serverConfig={serverConfig}
|
|
|
serverId={usePreConfigured ? selectedServerId : undefined}
|
|
|
+ projectPath={selectedPath}
|
|
|
/>
|
|
|
)}
|
|
|
{activeTab === 'logs' && (
|
|
|
<LogViewer
|
|
|
serverConfig={serverConfig}
|
|
|
serverId={usePreConfigured ? selectedServerId : undefined}
|
|
|
+ projectPath={selectedPath}
|
|
|
/>
|
|
|
)}
|
|
|
{activeTab === 'config' && (
|
|
|
<ConfigManager
|
|
|
serverConfig={serverConfig}
|
|
|
serverId={usePreConfigured ? selectedServerId : undefined}
|
|
|
+ projectPath={selectedPath}
|
|
|
/>
|
|
|
)}
|
|
|
</div>
|