增加GIT代码检测节点
This commit is contained in:
parent
2eaca114a4
commit
0e88904267
@ -61,8 +61,10 @@ export const ServerCard: React.FC<ServerCardProps> = ({ server, onTest, onEdit,
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="group relative flex h-full flex-col justify-between overflow-visible border transition-all duration-200 hover:border-primary/40 hover:shadow-lg">
|
<Card className={`group relative flex h-full flex-col justify-between overflow-visible border transition-all duration-200 hover:border-primary/40 hover:shadow-lg ${
|
||||||
<CardContent className="relative flex flex-1 flex-col gap-3 p-3">
|
expanded ? 'rounded-b-none border-b-0' : ''
|
||||||
|
}`}>
|
||||||
|
<CardContent className="flex flex-1 flex-col gap-3 p-3">
|
||||||
{/* 基础信息 */}
|
{/* 基础信息 */}
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex items-start gap-3">
|
||||||
<div className="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-muted/50">
|
<div className="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-muted/50">
|
||||||
@ -202,94 +204,94 @@ export const ServerCard: React.FC<ServerCardProps> = ({ server, onTest, onEdit,
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 展开内容 */}
|
|
||||||
{expanded && (
|
|
||||||
<div className="absolute left-0 right-0 top-full z-20 -mt-px space-y-3 rounded-b-xl border border-border border-t bg-card p-3 text-xs shadow-lg">
|
|
||||||
<div className="flex flex-wrap items-center gap-2">
|
|
||||||
{renderValue(
|
|
||||||
<span className="text-muted-foreground">
|
|
||||||
SSH:
|
|
||||||
<span className="ml-1 font-medium text-foreground">
|
|
||||||
{(server.sshUser || 'root') + ':' + (server.sshPort || 22)}
|
|
||||||
</span>
|
|
||||||
</span>,
|
|
||||||
'w-32'
|
|
||||||
)}
|
|
||||||
{server.authType && (
|
|
||||||
<Badge variant="secondary" className="text-[11px]">
|
|
||||||
{server.authType === 'PASSWORD' ? '密码认证' : '密钥认证'}
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="grid grid-cols-3 gap-2 text-center">
|
|
||||||
<div className="flex flex-col items-center gap-1">
|
|
||||||
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-primary/10 text-primary">
|
|
||||||
<Cpu className="h-4 w-4" />
|
|
||||||
</div>
|
|
||||||
{renderValue(
|
|
||||||
server.cpuCores ? (
|
|
||||||
<span className="text-xs font-medium text-foreground">{server.cpuCores}核</span>
|
|
||||||
) : null,
|
|
||||||
'w-10',
|
|
||||||
{ skeleton: true, skeletonHeight: 'h-4' }
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col items-center gap-1">
|
|
||||||
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-primary/10 text-primary">
|
|
||||||
<MemoryStick className="h-4 w-4" />
|
|
||||||
</div>
|
|
||||||
{renderValue(
|
|
||||||
server.memorySize ? (
|
|
||||||
<span className="text-xs font-medium text-foreground">{server.memorySize}GB</span>
|
|
||||||
) : null,
|
|
||||||
'w-10',
|
|
||||||
{ skeleton: true, skeletonHeight: 'h-4' }
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col items-center gap-1">
|
|
||||||
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-primary/10 text-primary">
|
|
||||||
<HardDrive className="h-4 w-4" />
|
|
||||||
</div>
|
|
||||||
{renderValue(
|
|
||||||
server.diskSize ? (
|
|
||||||
<span className="text-xs font-medium text-foreground">{server.diskSize}GB</span>
|
|
||||||
) : null,
|
|
||||||
'w-10',
|
|
||||||
{ skeleton: true, skeletonHeight: 'h-4' }
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{server.tags && (() => {
|
|
||||||
try {
|
|
||||||
const tags = JSON.parse(server.tags);
|
|
||||||
if (Array.isArray(tags) && tags.length > 0) {
|
|
||||||
return (
|
|
||||||
<div className="flex flex-wrap gap-1">
|
|
||||||
{tags.slice(0, 3).map((tag: string, index: number) => (
|
|
||||||
<Badge key={index} variant="outline" className="text-[11px]">
|
|
||||||
{tag}
|
|
||||||
</Badge>
|
|
||||||
))}
|
|
||||||
{tags.length > 3 && (
|
|
||||||
<Badge variant="outline" className="text-[11px]">+{tags.length - 3}</Badge>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
})()}
|
|
||||||
|
|
||||||
{server.description ? (
|
|
||||||
<p className="text-xs text-muted-foreground line-clamp-3">{server.description}</p>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|
||||||
|
{/* 展开内容 */}
|
||||||
|
{expanded && (
|
||||||
|
<div className="absolute left-[-1px] right-[-1px] top-full z-20 space-y-3 rounded-b-xl border-x border-b border-border bg-card p-3 text-xs shadow-lg group-hover:border-primary/40">
|
||||||
|
<div className="flex flex-wrap items-center gap-2">
|
||||||
|
{renderValue(
|
||||||
|
<span className="text-muted-foreground">
|
||||||
|
SSH:
|
||||||
|
<span className="ml-1 font-medium text-foreground">
|
||||||
|
{(server.sshUser || 'root') + ':' + (server.sshPort || 22)}
|
||||||
|
</span>
|
||||||
|
</span>,
|
||||||
|
'w-32'
|
||||||
|
)}
|
||||||
|
{server.authType && (
|
||||||
|
<Badge variant="secondary" className="text-[11px]">
|
||||||
|
{server.authType === 'PASSWORD' ? '密码认证' : '密钥认证'}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-3 gap-2 text-center">
|
||||||
|
<div className="flex flex-col items-center gap-1">
|
||||||
|
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-primary/10 text-primary">
|
||||||
|
<Cpu className="h-4 w-4" />
|
||||||
|
</div>
|
||||||
|
{renderValue(
|
||||||
|
server.cpuCores ? (
|
||||||
|
<span className="text-xs font-medium text-foreground">{server.cpuCores}核</span>
|
||||||
|
) : null,
|
||||||
|
'w-10',
|
||||||
|
{ skeleton: true, skeletonHeight: 'h-4' }
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center gap-1">
|
||||||
|
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-primary/10 text-primary">
|
||||||
|
<MemoryStick className="h-4 w-4" />
|
||||||
|
</div>
|
||||||
|
{renderValue(
|
||||||
|
server.memorySize ? (
|
||||||
|
<span className="text-xs font-medium text-foreground">{server.memorySize}GB</span>
|
||||||
|
) : null,
|
||||||
|
'w-10',
|
||||||
|
{ skeleton: true, skeletonHeight: 'h-4' }
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center gap-1">
|
||||||
|
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-primary/10 text-primary">
|
||||||
|
<HardDrive className="h-4 w-4" />
|
||||||
|
</div>
|
||||||
|
{renderValue(
|
||||||
|
server.diskSize ? (
|
||||||
|
<span className="text-xs font-medium text-foreground">{server.diskSize}GB</span>
|
||||||
|
) : null,
|
||||||
|
'w-10',
|
||||||
|
{ skeleton: true, skeletonHeight: 'h-4' }
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{server.tags && (() => {
|
||||||
|
try {
|
||||||
|
const tags = JSON.parse(server.tags);
|
||||||
|
if (Array.isArray(tags) && tags.length > 0) {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
|
{tags.slice(0, 3).map((tag: string, index: number) => (
|
||||||
|
<Badge key={index} variant="outline" className="text-[11px]">
|
||||||
|
{tag}
|
||||||
|
</Badge>
|
||||||
|
))}
|
||||||
|
{tags.length > 3 && (
|
||||||
|
<Badge variant="outline" className="text-[11px]">+{tags.length - 3}</Badge>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
})()}
|
||||||
|
|
||||||
|
{server.description ? (
|
||||||
|
<p className="text-xs text-muted-foreground line-clamp-3">{server.description}</p>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user