更新 ServerCard 组件,增加分组名称的显示功能,优化布局以提升信息展示的清晰度和可读性。同时在 Server 页面中查找服务器所属的分组并传递相关信息。

This commit is contained in:
wood chen 2025-04-29 02:34:46 +08:00
parent 8eec93aff4
commit 06f2e04ba8
2 changed files with 40 additions and 23 deletions

View File

@ -11,7 +11,7 @@ import PlanInfo from "./PlanInfo"
import BillingInfo from "./billingInfo" import BillingInfo from "./billingInfo"
import { Card, CardContent, CardHeader, CardFooter } from "./ui/card" import { Card, CardContent, CardHeader, CardFooter } from "./ui/card"
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./ui/tooltip" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./ui/tooltip"
import { ArrowDown, ArrowUp, Clock, Cpu, HardDrive, Server, Activity, BarChart3, Calendar } from "lucide-react" import { ArrowDown, ArrowUp, Clock, Cpu, HardDrive, Server, Activity, BarChart3 } from "lucide-react"
interface ServerCardProps { interface ServerCardProps {
now: number; now: number;
@ -19,9 +19,10 @@ interface ServerCardProps {
cycleStats?: { cycleStats?: {
[key: string]: CycleTransferData [key: string]: CycleTransferData
}; };
groupName?: string;
} }
export default function ServerCard({ now, serverInfo, cycleStats }: ServerCardProps) { export default function ServerCard({ now, serverInfo, cycleStats, groupName }: ServerCardProps) {
const { t } = useTranslation() const { t } = useTranslation()
const navigate = useNavigate() const navigate = useNavigate()
const { const {
@ -44,7 +45,6 @@ export default function ServerCard({ now, serverInfo, cycleStats }: ServerCardPr
udp, udp,
process, process,
uptime, uptime,
last_active_time_string,
arch, arch,
swap, swap,
swap_total swap_total
@ -201,7 +201,17 @@ export default function ServerCard({ now, serverInfo, cycleStats }: ServerCardPr
onClick={cardClick} onClick={cardClick}
> >
<div className="absolute top-0 left-0 w-1 h-full bg-red-500 rounded-l-md"></div> <div className="absolute top-0 left-0 w-1 h-full bg-red-500 rounded-l-md"></div>
<CardContent className="p-4">
{/* 离线卡片的分组标签 */}
{groupName && (
<div className="absolute top-2 right-2">
<div className="px-1.5 py-0.5 text-[10px] font-medium bg-red-100 text-red-700 dark:bg-red-900/40 dark:text-red-400 rounded-sm border border-red-200 dark:border-red-800">
{groupName}
</div>
</div>
)}
<CardContent className="p-4 pt-6">
<div className="flex items-center gap-3 mb-2"> <div className="flex items-center gap-3 mb-2">
<span className="h-3 w-3 shrink-0 rounded-full bg-red-500 shadow-sm pulse-animation shadow-red-300 dark:shadow-red-900"></span> <span className="h-3 w-3 shrink-0 rounded-full bg-red-500 shadow-sm pulse-animation shadow-red-300 dark:shadow-red-900"></span>
{showFlag && <ServerFlag country_code={country_code} />} {showFlag && <ServerFlag country_code={country_code} />}
@ -272,14 +282,20 @@ export default function ServerCard({ now, serverInfo, cycleStats }: ServerCardPr
)} )}
onClick={cardClick} onClick={cardClick}
> >
{/* 左侧状态条 */}
<div className="absolute top-0 left-0 w-1 h-full bg-green-500 rounded-l-md"></div> <div className="absolute top-0 left-0 w-1 h-full bg-green-500 rounded-l-md"></div>
<CardHeader className="p-4 pb-2"> <CardHeader className="p-4 pb-2 pt-2">
<div className="flex justify-between"> <div className="flex justify-between">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<span className="h-3 w-3 shrink-0 rounded-full bg-green-500 shadow-sm shadow-green-300 dark:shadow-green-900 animate-pulse"></span> <span className="h-3 w-3 shrink-0 rounded-full bg-green-500 shadow-sm shadow-green-300 dark:shadow-green-900 animate-pulse"></span>
{showFlag && <ServerFlag country_code={country_code} />} {showFlag && <ServerFlag country_code={country_code} />}
<h3 className="font-bold text-sm truncate">{name}</h3> <h3 className="font-bold text-sm truncate">{name}</h3>
{groupName && (
<div className="px-1.5 py-0.5 text-[10px] font-medium bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-400 rounded-sm border border-green-200 dark:border-green-800">
{groupName}
</div>
)}
</div> </div>
<div className="flex items-center text-xs gap-2 text-muted-foreground"> <div className="flex items-center text-xs gap-2 text-muted-foreground">
@ -308,13 +324,6 @@ export default function ServerCard({ now, serverInfo, cycleStats }: ServerCardPr
<span>{formatUptime(uptime, t)}</span> <span>{formatUptime(uptime, t)}</span>
</div> </div>
)} )}
{last_active_time_string && (
<div className="flex items-center text-xs text-muted-foreground">
<Calendar className="size-[12px] mr-1" />
<span>{last_active_time_string}</span>
</div>
)}
</div> </div>
</div> </div>
</CardHeader> </CardHeader>

View File

@ -335,14 +335,22 @@ export default function Servers() {
{showMap === "1" && <GlobalMap now={nezhaWsData.now} serverList={nezhaWsData?.servers || []} />} {showMap === "1" && <GlobalMap now={nezhaWsData.now} serverList={nezhaWsData?.servers || []} />}
{showServices === "1" && <ServiceTracker serverList={filteredServers} />} {showServices === "1" && <ServiceTracker serverList={filteredServers} />}
<section ref={containerRef} className="grid grid-cols-1 gap-4 md:grid-cols-3 mt-6 server-card-list"> <section ref={containerRef} className="grid grid-cols-1 gap-4 md:grid-cols-3 mt-6 server-card-list">
{filteredServers.map((serverInfo) => ( {filteredServers.map((serverInfo) => {
// 查找服务器所属的分组
const serverGroup = groupData?.data?.find(
(g: ServerGroup) => Array.isArray(g.servers) && g.servers.includes(serverInfo.id)
);
return (
<ServerCard <ServerCard
now={nezhaWsData.now} now={nezhaWsData.now}
key={serverInfo.id} key={serverInfo.id}
serverInfo={serverInfo} serverInfo={serverInfo}
cycleStats={cycleTransferStats} cycleStats={cycleTransferStats}
groupName={serverGroup?.group.name}
/> />
))} );
})}
</section> </section>
</div> </div>
) )