From 11e8c24f3727788468e6ada8f012846b10223956 Mon Sep 17 00:00:00 2001 From: attacker Date: Fri, 19 Jun 2026 01:31:46 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20CSV/=E4=BA=91=E5=B9=B3=E5=8F=B0?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E6=B7=BB=E5=8A=A0SSH=E7=AB=AF=E5=8F=A3(?= =?UTF-8?q?=E9=BB=98=E8=AE=A422)=20+=20=E5=87=AD=E8=AF=81=E5=85=B3?= =?UTF-8?q?=E8=81=94=E4=B8=8B=E6=8B=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CSV模板新增port列, 连接方式改为SSH端口输入(默认22) - 云平台导入新增SSH端口配置 + 凭证下拉选择 - 移除冗余的连接方式(密码/密钥)选择 → 凭证下拉统一管理 - ExcelServerImport: template含port列, resetState包含新字段 --- .../components/server/CloudServerImport.tsx | 55 ++++++++++++++++++- .../components/server/ExcelServerImport.tsx | 55 ++++++++----------- 2 files changed, 75 insertions(+), 35 deletions(-) diff --git a/frontend/src/components/server/CloudServerImport.tsx b/frontend/src/components/server/CloudServerImport.tsx index c4fbe69..aa1e14c 100644 --- a/frontend/src/components/server/CloudServerImport.tsx +++ b/frontend/src/components/server/CloudServerImport.tsx @@ -57,6 +57,9 @@ export function CloudServerImport({ open, onClose }: CloudServerImportProps) { const [discoverErrors, setDiscoverErrors] = useState([]); const [isImporting, setIsImporting] = useState(false); const [importResult, setImportResult] = useState<{ imported: number; skipped: number } | null>(null); + const [defaultSshPort, setDefaultSshPort] = useState('22'); + const [credentials, setCredentials] = useState([]); + const [selectedCredentialId, setSelectedCredentialId] = useState(''); const loadAccounts = async () => { try { @@ -68,7 +71,13 @@ export function CloudServerImport({ open, onClose }: CloudServerImportProps) { }; useEffect(() => { - if (open) loadAccounts(); + if (open) { + loadAccounts(); + import('@/services/api').then(({ credentialApi }) => { + credentialApi.list().then((res: any) => setCredentials(res?.list || [])) + .catch(() => setCredentials([])); + }); + } }, [open]); const filteredAccounts = cloudAccounts.filter( @@ -140,7 +149,10 @@ export function CloudServerImport({ open, onClose }: CloudServerImportProps) { setIsImporting(true); try { const instancesToImport = cloudServers.filter(s => selectedServers.includes(s.instance_id)); - const res: any = await cloudApi.importInstances(selectedAccount.id, instancesToImport); + const res: any = await cloudApi.importInstances(selectedAccount.id, instancesToImport, { + default_port: Number(defaultSshPort) || 22, + credential_id: selectedCredentialId ? Number(selectedCredentialId) : undefined, + }); setImportResult(res || { imported: 0, skipped: 0 }); } catch (e: any) { console.error('导入失败:', e); @@ -199,6 +211,8 @@ export function CloudServerImport({ open, onClose }: CloudServerImportProps) { setRegionSearch(''); setDiscoverErrors([]); setImportResult(null); + setDefaultSshPort('22'); + setSelectedCredentialId(''); }; const filteredRegions = regions.filter(r => @@ -545,6 +559,43 @@ export function CloudServerImport({ open, onClose }: CloudServerImportProps) { )} + + {/* SSH 端口 + 凭证关联 */} + {cloudServers.length > 0 && selectedServers.length > 0 && ( +
+
+ + setDefaultSshPort(e.target.value)} + className="w-32 bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)] text-[var(--dg-text-primary)]" + /> +
+
+ + +
+
+ )} )} diff --git a/frontend/src/components/server/ExcelServerImport.tsx b/frontend/src/components/server/ExcelServerImport.tsx index 0974006..f554a35 100644 --- a/frontend/src/components/server/ExcelServerImport.tsx +++ b/frontend/src/components/server/ExcelServerImport.tsx @@ -36,11 +36,6 @@ interface ExcelServerImportProps { onClose: () => void; } -const connectionMethods = [ - { id: 'password', name: '密码认证', description: '使用用户名密码连接' }, - { id: 'key', name: '密钥认证', description: '使用SSH密钥连接' }, -]; - type PreviewRow = { row: number; hostname: string; ip: string; port: number; username: string; os: string; cpu: number; memory: number; disk: number; tags: string; @@ -94,13 +89,13 @@ function isValidIP(ip: string): boolean { return /^(\d{1,3}\.){3}\d{1,3}$/.test(ip) && ip.split('.').every((o) => Number(o) >= 0 && Number(o) <= 255); } -// 下载 CSV 导入模板 — 只需 hostname + ip,端口默认22 账号默认root,Agent 安装后自动补全 // Logan.Li +// 下载 CSV 导入模板 — 主机名+IP+端口(默认22),账号root,Agent 安装后自动补全 // Logan.Li function downloadTemplate() { const csv = [ - 'hostname,ip', - 'web-01,192.168.1.10', - 'db-01,192.168.1.20', - 'cache-01,192.168.1.30', + 'hostname,ip,port', + 'web-01,192.168.1.10,22', + 'db-01,192.168.1.20,22', + 'cache-01,192.168.1.30,2222', ].join('\n'); const blob = new Blob(['\ufeff' + csv], { type: 'text/csv;charset=utf-8;' }); const url = URL.createObjectURL(blob); @@ -123,6 +118,7 @@ export function ExcelServerImport({ open, onClose }: ExcelServerImportProps) { // 凭据选择 // Logan.Li const [credentials, setCredentials] = useState([]); const [selectedCredentialId, setSelectedCredentialId] = useState(''); + const [defaultSshPort, setDefaultSshPort] = useState('22'); // 对话框打开时拉取区域列表 + 凭据列表 // Logan.Li useEffect(() => { @@ -221,7 +217,8 @@ export function ExcelServerImport({ open, onClose }: ExcelServerImportProps) { const resetState = () => { setStep(1); setSelectedRegion(''); - setConnectionMethod('password'); + setDefaultSshPort('22'); + setSelectedCredentialId(''); setSelectedFile(null); setPreviewData([]); }; @@ -245,8 +242,8 @@ export function ExcelServerImport({ open, onClose }: ExcelServerImportProps) { const resp: any = await serverApi.batchCreate({ servers, region_id: selectedRegion || undefined, - auth_type: connectionMethod, credential_id: selectedCredentialId ? Number(selectedCredentialId) : undefined, + default_port: Number(defaultSshPort) || 22, }); const r = resp ?? {}; const success = r.success ?? 0; @@ -321,7 +318,7 @@ export function ExcelServerImport({ open, onClose }: ExcelServerImportProps) {

主机导入模板

-

下载 CSV 模板,只填主机名和 IP,端口默认22、账号默认root

+

下载 CSV 模板,只需填主机名、IP和端口(默认22),Agent安装后自动补全