用户反馈 /deployments 卡片按钮布局乱,且「日志查询」「采集器」和 endpoint 跳转按钮多余。
问题根因:
1. ResourceCard 的操作区是 flex 但没有 flex-wrap,
而 DeploymentCard 在部署/停止/重启按钮上用了 flex-1,
窄卡片里 7 个按钮互相挤压、换行错位、宽度不均
2. endpoint 在 K8s 模式下是 http://loki.log.svc.cluster.local:3100
这类集群内地址,浏览器点不开,展示出来纯属噪音
修复:
- ResourceCard 操作区加 flex-wrap + items-center(按钮多时自动规整换行)
- DeploymentCard 去掉 4 处 flex-1(按钮按内容宽度排布)
- 去掉「访问」字段(不再展示 cluster-local endpoint)
- 去掉「日志查询」跳转按钮(左下导航已有入口)
- 去掉「采集器」跳转按钮(同上)
- 去掉 endpoint 的 ExternalLink 跳转按钮
- 清理不再使用的 import:Link(react-router)、ExternalLink(lucide)
卡片保留的按钮:配置 / 部署(或 停止+重启)/ 日志 / 删除
镜像:lghost/lokistack:latest + v0.1 = sha256:d89b9cfa0054
99 lines
3.4 KiB
TypeScript
99 lines
3.4 KiB
TypeScript
import { memo } from 'react'
|
|
import type { LucideIcon } from 'lucide-react'
|
|
import { Card, CardContent } from '@/components/ui/card'
|
|
import { cn } from '@/lib/utils'
|
|
|
|
export interface ResourceField {
|
|
label: string
|
|
value: React.ReactNode
|
|
/** 值提示(截断时 title) */
|
|
title?: string
|
|
}
|
|
|
|
interface ResourceCardProps {
|
|
/** 头部图标 */
|
|
icon: LucideIcon
|
|
/** 图标配色(text-info/success/warning 等语义 token 类) */
|
|
iconClassName?: string
|
|
title: string
|
|
/** 标题旁附加(如 ready 状态点、uuid) */
|
|
titleExtra?: React.ReactNode
|
|
/** 右上角徽章(状态/保留天数等) */
|
|
badges?: React.ReactNode
|
|
/** 副标题/描述(单行截断) */
|
|
description?: string
|
|
/** 信息字段(两列网格;奇数个最后一项占整行) */
|
|
fields: ResourceField[]
|
|
/** 底部状态消息(如错误信息,浅底块) */
|
|
message?: string
|
|
/** 底部操作区(border-top 分隔) */
|
|
actions: React.ReactNode
|
|
}
|
|
|
|
/**
|
|
* 资源卡片 — 五大资源页(集群/主机/存储/部署/采集)统一样式:
|
|
* 图标+标题+徽章 → 描述 → 两列信息网格(label 上 value 下) → 分隔线操作区。
|
|
* 统一 p-4 内边距、hover 阴影、等高布局(网格内自动对齐)。
|
|
*/
|
|
export const ResourceCard = memo(function ResourceCard({
|
|
icon: Icon,
|
|
iconClassName = 'text-muted-foreground',
|
|
title,
|
|
titleExtra,
|
|
badges,
|
|
description,
|
|
fields,
|
|
message,
|
|
actions,
|
|
}: ResourceCardProps) {
|
|
return (
|
|
<Card className="border-border hover:shadow-md transition-shadow h-full">
|
|
<CardContent className="p-4 flex flex-col gap-3 h-full">
|
|
{/* 头部:图标 + 标题 + 徽章 */}
|
|
<div className="flex items-start gap-3">
|
|
<div className="w-9 h-9 rounded-lg bg-muted/70 flex items-center justify-center shrink-0">
|
|
<Icon className={cn('size-4', iconClassName)} />
|
|
</div>
|
|
<div className="min-w-0 flex-1">
|
|
<div className="flex items-center gap-2 flex-wrap">
|
|
<h3 className="font-medium text-sm text-foreground truncate" title={title}>
|
|
{title}
|
|
</h3>
|
|
{titleExtra}
|
|
{badges && <span className="ml-auto flex items-center gap-1.5 shrink-0">{badges}</span>}
|
|
</div>
|
|
{description && (
|
|
<p className="text-xs text-muted-foreground truncate mt-0.5" title={description}>
|
|
{description}
|
|
</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* 信息:两列网格(label 灰小字在上,value 在下) */}
|
|
<div className="grid grid-cols-2 gap-x-4 gap-y-2 text-xs">
|
|
{fields.map((f) => (
|
|
<div key={f.label} className="min-w-0">
|
|
<p className="text-muted-foreground leading-4">{f.label}</p>
|
|
<p className="font-medium text-foreground truncate leading-5" title={f.title}>
|
|
{f.value}
|
|
</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* 状态消息(错误/提示) */}
|
|
{message && (
|
|
<p className="rounded-md bg-muted/60 px-2.5 py-1.5 text-xs text-muted-foreground" title={message}>
|
|
{message}
|
|
</p>
|
|
)}
|
|
|
|
{/* 操作区:贴底 */}
|
|
{/* flex-wrap:按钮多时自动换行,避免在窄卡片里被 flex-1 压扁/溢出 */}
|
|
<div className="flex flex-wrap items-center gap-2 pt-3 border-t border-border mt-auto">{actions}</div>
|
|
</CardContent>
|
|
</Card>
|
|
)
|
|
})
|