feat(nodes): 调整节点详情 Tab 并新增边缘部署命令

将数据看板并入概览,运行状态与配置合并为状态与部署;
边缘节点支持自动填充 Server URL 与 Agent Token 的 Docker 部署卡片。
This commit is contained in:
ryan
2026-07-19 15:01:38 +08:00
parent 7366832e12
commit c00ead9aa0
7 changed files with 81 additions and 55 deletions
@@ -18,6 +18,7 @@ import { Label } from '@/components/ui/label';
import { type NodeItem, StatusService } from '@/lib/services/openflare';
import {
buildEdgeDockerInstallCommand,
buildRelayDockerInstallCommand,
buildRelayInstallCommand,
buildTunnelDockerInstallCommand,
@@ -25,7 +26,7 @@ import {
getServerUrl,
} from './node-utils';
type InstallVariant = 'relay' | 'tunnel';
type InstallVariant = 'edge' | 'relay' | 'tunnel';
const variantMeta: Record<
InstallVariant,
@@ -33,10 +34,16 @@ const variantMeta: Record<
title: string;
description: string;
tokenLabel: string;
scriptLabel: string;
scriptLabel?: string;
dockerLabel: string;
}
> = {
edge: {
title: '边缘节点部署',
description: '使用 Agent Token 将边缘节点接入控制端。',
tokenLabel: 'Agent Token',
dockerLabel: 'Docker 容器部署',
},
relay: {
title: '中继部署命令',
description: '使用 Discovery Token 将 frps 中继节点接入控制端。',
@@ -79,7 +86,7 @@ export function InstallCommand({
const normalizedServerUrl = getServerUrl(serverUrl);
const scriptCommand = useMemo(() => {
if (!normalizedServerUrl || !node.access_token) {
if (!normalizedServerUrl || !node.access_token || variant === 'edge') {
return '';
}
return variant === 'relay'
@@ -91,6 +98,13 @@ export function InstallCommand({
if (!normalizedServerUrl || !node.access_token) {
return '';
}
if (variant === 'edge') {
return buildEdgeDockerInstallCommand(
normalizedServerUrl,
node.access_token,
serverVersion,
);
}
return variant === 'relay'
? buildRelayDockerInstallCommand(
normalizedServerUrl,
@@ -190,12 +204,14 @@ export function InstallCommand({
</p>
) : (
<>
<div className='space-y-2'>
<p className='text-sm font-medium'>{meta.scriptLabel}</p>
<pre className='overflow-x-auto rounded-lg border bg-muted/40 p-3 text-xs whitespace-pre-wrap'>
{scriptCommand}
</pre>
</div>
{scriptCommand && meta.scriptLabel ? (
<div className='space-y-2'>
<p className='text-sm font-medium'>{meta.scriptLabel}</p>
<pre className='overflow-x-auto rounded-lg border bg-muted/40 p-3 text-xs whitespace-pre-wrap'>
{scriptCommand}
</pre>
</div>
) : null}
<div className='space-y-2'>
<p className='text-sm font-medium'>{meta.dockerLabel}</p>
<pre className='overflow-x-auto rounded-lg border bg-muted/40 p-3 text-xs whitespace-pre-wrap'>