feat: 完善堡垒机与 Agent 智能运维能力
- 支持 Windows Agent 构建、安装脚本和统一上报协议 - 增强 RDP 剪贴板、虚拟盘和文件传输能力 - 新增 AIOps 上下文工具、告警 RCA trace 落库和回放接口 - 重构 docs 模块文档并补充终端、堡垒机、监控、AI Agent 设计
This commit is contained in:
1 parent
a9513c2056
commit
e0d652d211
169 files changed
+12192
-9116
No files matched your search
@@ -43,6 +43,7 @@ function detectServerAddress() {
|
||||
export function AgentWizard({ open, onOpenChange, server, onStart, onInstalled, onFailed }: AgentWizardProps) {
|
||||
const token = useUserStore((s) => s.token) || '<YOUR_TOKEN>';
|
||||
const origin = detectServerAddress();
|
||||
const isWindowsServer = Boolean(server?.os && server.os.toLowerCase().includes('windows'));
|
||||
const [copied, setCopied] = useState(false);
|
||||
const [showManualInput, setShowManualInput] = useState(false);
|
||||
const [sshInstalling, setSshInstalling] = useState(false);
|
||||
@@ -50,9 +51,9 @@ export function AgentWizard({ open, onOpenChange, server, onStart, onInstalled,
|
||||
// 有目标主机时默认展示 SSH 一键安装页,无需用户再点一次 tab // Logan.Li
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
setActiveTab(server ? 'ssh' : 'auto');
|
||||
setActiveTab(server && !isWindowsServer ? 'ssh' : 'auto');
|
||||
}
|
||||
}, [open, server]);
|
||||
}, [open, server, isWindowsServer]);
|
||||
// 凭据输入(当服务器无认证凭据时显示)
|
||||
const [sshUsername, setSshUsername] = useState('root');
|
||||
const [sshPassword, setSshPassword] = useState('');
|
||||
@@ -62,7 +63,9 @@ export function AgentWizard({ open, onOpenChange, server, onStart, onInstalled,
|
||||
const needsCreds = server && !server.has_auth;
|
||||
|
||||
// install.sh 与 Agent 上报均走页面 origin(Nginx/Vite proxy 统一转发到后端)// Logan.Li
|
||||
const installCommand = `curl -fsSL ${origin}/agent/install.sh | bash -s -- --server ${origin} --token ${token}`;
|
||||
const linuxInstallCommand = `curl -fsSL ${origin}/agent/install.sh | bash -s -- --server ${origin} --token ${token}`;
|
||||
const windowsInstallCommand = `powershell -ExecutionPolicy Bypass -Command "iwr ${origin}/agent/install.ps1 -UseBasicParsing -OutFile $env:TEMP\\install-aiops-agent.ps1; & $env:TEMP\\install-aiops-agent.ps1 -Server '${origin}' -Token '${token}'"`;
|
||||
const installCommand = isWindowsServer ? windowsInstallCommand : linuxInstallCommand;
|
||||
|
||||
const handleCopy = () => {
|
||||
const textArea = document.createElement('textarea');
|
||||
@@ -114,6 +117,7 @@ export function AgentWizard({ open, onOpenChange, server, onStart, onInstalled,
|
||||
};
|
||||
|
||||
const binaryUrl = `${origin}/agent/aiops-agent-linux-amd64`;
|
||||
const windowsBinaryUrl = `${origin}/agent/aiops-agent-windows-amd64.exe`;
|
||||
|
||||
const manualSteps = [
|
||||
{
|
||||
@@ -158,11 +162,40 @@ export function AgentWizard({ open, onOpenChange, server, onStart, onInstalled,
|
||||
],
|
||||
},
|
||||
];
|
||||
const windowsManualSteps = [
|
||||
{
|
||||
icon: Download,
|
||||
title: '下载 Windows Agent',
|
||||
commands: [
|
||||
`New-Item -ItemType Directory -Force "C:\\Program Files\\AIOps"`,
|
||||
`Invoke-WebRequest -Uri ${windowsBinaryUrl} -OutFile "C:\\Program Files\\AIOps\\aiops-agent.exe" -UseBasicParsing`,
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: Cpu,
|
||||
title: '注册 Windows 服务',
|
||||
commands: [
|
||||
`New-Service -Name AIOpsAgent -DisplayName "AIOps Agent" -BinaryPathName '"C:\\Program Files\\AIOps\\aiops-agent.exe" -server ${origin} -interval 10 -token ${token}' -StartupType Automatic`,
|
||||
],
|
||||
},
|
||||
{
|
||||
icon: Play,
|
||||
title: '启动并检查',
|
||||
commands: [
|
||||
'Start-Service AIOpsAgent',
|
||||
'Get-Service AIOpsAgent',
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// SSH 一键安装(当从服务器列表传入 server 上下文时可用)
|
||||
// 改为调用批量异步接口,单台也走后台 goroutine 执行,避免前端长时间等待 // Logan.Li
|
||||
const handleSshInstall = async () => {
|
||||
if (!server || !token) return;
|
||||
if (isWindowsServer) {
|
||||
toast.error('Windows Agent 请使用 PowerShell 安装命令,SSH 一键安装仅支持 Linux/macOS');
|
||||
return;
|
||||
}
|
||||
if (needsCreds && !sshPassword && !sshKey) {
|
||||
toast.error(i18n.t('agent.agentwizardtsx.s6cfe961c'));
|
||||
return;
|
||||
@@ -214,12 +247,12 @@ export function AgentWizard({ open, onOpenChange, server, onStart, onInstalled,
|
||||
<TabsList className="bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)]">
|
||||
<TabsTrigger value="auto" className="data-[state=active]:bg-[var(--dg-bg-active)]">
|
||||
<Terminal className="h-4 w-4 mr-1.5" />
|
||||
{t('agent.agentwizardtsx.s1a2b3c4d')}
|
||||
{isWindowsServer ? 'PowerShell 安装' : i18n.t('agent.agentwizardtsx.s1a2b3c4d')}
|
||||
</TabsTrigger>
|
||||
{server && (
|
||||
{server && !isWindowsServer && (
|
||||
<TabsTrigger value="ssh" className="data-[state=active]:bg-[var(--dg-bg-active)]">
|
||||
<Zap className="h-4 w-4 mr-1.5" />
|
||||
{t('agent.agentwizardtsx.s2b3c4d5e')}
|
||||
{i18n.t('agent.agentwizardtsx.s2b3c4d5e')}
|
||||
</TabsTrigger>
|
||||
)}
|
||||
{!server && (
|
||||
@@ -229,14 +262,14 @@ export function AgentWizard({ open, onOpenChange, server, onStart, onInstalled,
|
||||
</TabsTrigger>
|
||||
)}
|
||||
<TabsTrigger value="manual" className="data-[state=active]:bg-[var(--dg-bg-active)]">
|
||||
{t('agent.agentwizardtsx.s3c4d5e6f')}
|
||||
{i18n.t('agent.agentwizardtsx.s3c4d5e6f')}
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
{/* 自动安装 */}
|
||||
<TabsContent value="auto" className="mt-4 space-y-3">
|
||||
<p className="text-sm dg-text-secondary">
|
||||
{t('agent.agentwizardtsx.s4d5e6f7g')}
|
||||
{isWindowsServer ? '请在目标 Windows 主机的管理员 PowerShell 中执行以下命令。' : i18n.t('agent.agentwizardtsx.s4d5e6f7g')}
|
||||
</p>
|
||||
<div className="relative rounded-lg bg-[var(--dg-bg-primary)] border border-[var(--dg-border)] p-4">
|
||||
<pre className="text-xs dg-text-green font-mono whitespace-pre-wrap break-all pr-10">
|
||||
@@ -257,7 +290,7 @@ export function AgentWizard({ open, onOpenChange, server, onStart, onInstalled,
|
||||
{showManualInput && (
|
||||
<div className="rounded-lg bg-amber-950/30 border border-amber-800/50 p-4">
|
||||
<p className="text-xs dg-text-yellow mb-2">
|
||||
{t('agent.agentwizardtsx.s5e6f7g8h')}
|
||||
{i18n.t('agent.agentwizardtsx.s5e6f7g8h')}
|
||||
</p>
|
||||
<textarea
|
||||
readOnly
|
||||
@@ -322,17 +355,17 @@ export function AgentWizard({ open, onOpenChange, server, onStart, onInstalled,
|
||||
className="h-8 text-sm dg-input text-[var(--dg-text-primary)] mt-1"
|
||||
/>
|
||||
</div>
|
||||
<span className="text-xs dg-text-muted px-1 pb-1">{t("agent.agentwizardtsx.s1k2l3m4n")}</span>
|
||||
<span className="text-xs dg-text-muted px-1 pb-1">{i18n.t("agent.agentwizardtsx.s1k2l3m4n")}</span>
|
||||
<Button variant="ghost" size="sm"
|
||||
onClick={() => { setAuthType('key'); setSshPassword(''); }}
|
||||
className={`text-xs h-7 px-2 ${authType==='key'?'dg-text-blue':'dg-text-muted'}`}>
|
||||
{t('agent.agentwizardtsx.s2l3m4n5o')}
|
||||
{i18n.t('agent.agentwizardtsx.s2l3m4n5o')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{authType === 'key' && (
|
||||
<div>
|
||||
<Label className="text-xs dg-text-secondary">{t("agent.agentwizardtsx.s3m4n5o6p")}</Label>
|
||||
<Label className="text-xs dg-text-secondary">{i18n.t("agent.agentwizardtsx.s3m4n5o6p")}</Label>
|
||||
<textarea
|
||||
value={sshKey}
|
||||
onChange={e => setSshKey(e.target.value)}
|
||||
@@ -346,7 +379,7 @@ export function AgentWizard({ open, onOpenChange, server, onStart, onInstalled,
|
||||
)}
|
||||
|
||||
<p className="text-sm dg-text-secondary mb-4">
|
||||
{t("agent.agentwizardtsx.s7g8h9i0j")}
|
||||
{i18n.t("agent.agentwizardtsx.s7g8h9i0j")}
|
||||
</p>
|
||||
<Button
|
||||
onClick={handleSshInstall}
|
||||
@@ -356,7 +389,7 @@ export function AgentWizard({ open, onOpenChange, server, onStart, onInstalled,
|
||||
{sshInstalling ? (
|
||||
<>
|
||||
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
|
||||
{t('agent.agentwizardtsx.s8h9i0j1k')}
|
||||
{i18n.t('agent.agentwizardtsx.s8h9i0j1k')}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
@@ -379,7 +412,7 @@ export function AgentWizard({ open, onOpenChange, server, onStart, onInstalled,
|
||||
{/* 手动安装 */}
|
||||
<TabsContent value="manual" className="mt-4 space-y-4">
|
||||
<div className="max-h-[420px] overflow-y-auto space-y-3 pr-1">
|
||||
{manualSteps.map((step) => (
|
||||
{(isWindowsServer ? windowsManualSteps : manualSteps).map((step) => (
|
||||
<div key={step.title} className="rounded-lg bg-[var(--dg-bg-primary)] border border-[var(--dg-border)] overflow-hidden">
|
||||
<div className="flex items-center gap-2 px-4 py-2.5 bg-[var(--dg-bg-tertiary)]/50">
|
||||
<step.icon className="h-4 w-4 dg-text-blue" />
|
||||
@@ -399,7 +432,7 @@ export function AgentWizard({ open, onOpenChange, server, onStart, onInstalled,
|
||||
))}
|
||||
</div>
|
||||
<p className="text-xs dg-text-muted">
|
||||
{t('agent.agentwizardtsx.s0j1k2l3m')}
|
||||
{i18n.t('agent.agentwizardtsx.s0j1k2l3m')}
|
||||
</p>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
||||
Reference in new issue
Block a user