mirror of
https://github.com/woodchen-ink/nezha-dash-v1.git
synced 2025-07-18 17:41:56 +08:00
feat: detail overview i18n
This commit is contained in:
parent
8812cd1d3f
commit
ee03928a56
@ -1,7 +1,9 @@
|
|||||||
// src/components/Footer.tsx
|
// src/components/Footer.tsx
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const Footer: React.FC = () => {
|
const Footer: React.FC = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<footer className="mx-auto w-full max-w-5xl px-4 lg:px-0 pb-4">
|
<footer className="mx-auto w-full max-w-5xl px-4 lg:px-0 pb-4">
|
||||||
<section className="flex flex-col">
|
<section className="flex flex-col">
|
||||||
@ -13,7 +15,7 @@ const Footer: React.FC = () => {
|
|||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Theme by{" "}
|
{t("footer.themeBy")}
|
||||||
<a
|
<a
|
||||||
href={"https://github.com/hamster1963/nezha-dash-react"}
|
href={"https://github.com/hamster1963/nezha-dash-react"}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
@ -5,10 +5,11 @@ import { fetchLoginUser } from "@/lib/nezha-api";
|
|||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { LanguageSwitcher } from "./LanguageSwitcher";
|
import { LanguageSwitcher } from "./LanguageSwitcher";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
function Header() {
|
function Header() {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto w-full max-w-5xl">
|
<div className="mx-auto w-full max-w-5xl">
|
||||||
<section className="flex items-center justify-between">
|
<section className="flex items-center justify-between">
|
||||||
@ -28,7 +29,7 @@ function Header() {
|
|||||||
className="mx-2 hidden h-4 w-[1px] md:block"
|
className="mx-2 hidden h-4 w-[1px] md:block"
|
||||||
/>
|
/>
|
||||||
<p className="hidden text-sm font-medium opacity-40 md:block">
|
<p className="hidden text-sm font-medium opacity-40 md:block">
|
||||||
哪吒监控
|
{t("nezha")}
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
<section className="flex items-center gap-2">
|
<section className="flex items-center gap-2">
|
||||||
@ -98,7 +99,7 @@ function Overview() {
|
|||||||
<section className={"mt-10 flex flex-col md:mt-16"}>
|
<section className={"mt-10 flex flex-col md:mt-16"}>
|
||||||
<p className="text-base font-semibold">👋 {t("overview")}</p>
|
<p className="text-base font-semibold">👋 {t("overview")}</p>
|
||||||
<div className="flex items-center gap-1.5">
|
<div className="flex items-center gap-1.5">
|
||||||
<p className="text-sm font-medium opacity-50">where the time is</p>
|
<p className="text-sm font-medium opacity-50">{t("whereTheTimeIs")}</p>
|
||||||
{mouted ? (
|
{mouted ? (
|
||||||
<p className="text-sm font-medium">{timeString}</p>
|
<p className="text-sm font-medium">{timeString}</p>
|
||||||
) : (
|
) : (
|
||||||
|
@ -5,8 +5,10 @@ import { cn, formatNezhaInfo } from "@/lib/utils";
|
|||||||
import { NezhaAPI } from "@/types/nezha-api";
|
import { NezhaAPI } from "@/types/nezha-api";
|
||||||
import { Card } from "./ui/card";
|
import { Card } from "./ui/card";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
export default function ServerCard({ serverInfo }: { serverInfo: NezhaAPI }) {
|
export default function ServerCard({ serverInfo }: { serverInfo: NezhaAPI }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { name, country_code, online, cpu, up, down, mem, stg } =
|
const { name, country_code, online, cpu, up, down, mem, stg } =
|
||||||
formatNezhaInfo(serverInfo);
|
formatNezhaInfo(serverInfo);
|
||||||
@ -55,21 +57,27 @@ export default function ServerCard({ serverInfo }: { serverInfo: NezhaAPI }) {
|
|||||||
<ServerUsageBar value={cpu} />
|
<ServerUsageBar value={cpu} />
|
||||||
</div>
|
</div>
|
||||||
<div className={"flex w-14 flex-col"}>
|
<div className={"flex w-14 flex-col"}>
|
||||||
<p className="text-xs text-muted-foreground">{"MEM"}</p>
|
<p className="text-xs text-muted-foreground">
|
||||||
|
{t("serverCard.mem")}
|
||||||
|
</p>
|
||||||
<div className="flex items-center text-xs font-semibold">
|
<div className="flex items-center text-xs font-semibold">
|
||||||
{mem.toFixed(2)}%
|
{mem.toFixed(2)}%
|
||||||
</div>
|
</div>
|
||||||
<ServerUsageBar value={mem} />
|
<ServerUsageBar value={mem} />
|
||||||
</div>
|
</div>
|
||||||
<div className={"flex w-14 flex-col"}>
|
<div className={"flex w-14 flex-col"}>
|
||||||
<p className="text-xs text-muted-foreground">{"STG"}</p>
|
<p className="text-xs text-muted-foreground">
|
||||||
|
{t("serverCard.stg")}
|
||||||
|
</p>
|
||||||
<div className="flex items-center text-xs font-semibold">
|
<div className="flex items-center text-xs font-semibold">
|
||||||
{stg.toFixed(2)}%
|
{stg.toFixed(2)}%
|
||||||
</div>
|
</div>
|
||||||
<ServerUsageBar value={stg} />
|
<ServerUsageBar value={stg} />
|
||||||
</div>
|
</div>
|
||||||
<div className={"flex w-14 flex-col"}>
|
<div className={"flex w-14 flex-col"}>
|
||||||
<p className="text-xs text-muted-foreground">{"Upload"}</p>
|
<p className="text-xs text-muted-foreground">
|
||||||
|
{t("serverCard.upload")}
|
||||||
|
</p>
|
||||||
<div className="flex items-center text-xs font-semibold">
|
<div className="flex items-center text-xs font-semibold">
|
||||||
{up >= 1024
|
{up >= 1024
|
||||||
? `${(up / 1024).toFixed(2)}G/s`
|
? `${(up / 1024).toFixed(2)}G/s`
|
||||||
@ -77,7 +85,9 @@ export default function ServerCard({ serverInfo }: { serverInfo: NezhaAPI }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={"flex w-14 flex-col"}>
|
<div className={"flex w-14 flex-col"}>
|
||||||
<p className="text-xs text-muted-foreground">{"Download"}</p>
|
<p className="text-xs text-muted-foreground">
|
||||||
|
{t("serverCard.download")}
|
||||||
|
</p>
|
||||||
<div className="flex items-center text-xs font-semibold">
|
<div className="flex items-center text-xs font-semibold">
|
||||||
{down >= 1024
|
{down >= 1024
|
||||||
? `${(down / 1024).toFixed(2)}G/s`
|
? `${(down / 1024).toFixed(2)}G/s`
|
||||||
|
@ -7,18 +7,18 @@ import { useWebSocketContext } from "@/hooks/use-websocket-context";
|
|||||||
import { cn, formatBytes, formatNezhaInfo } from "@/lib/utils";
|
import { cn, formatBytes, formatNezhaInfo } from "@/lib/utils";
|
||||||
import { NezhaAPIResponse } from "@/types/nezha-api";
|
import { NezhaAPIResponse } from "@/types/nezha-api";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
export default function ServerDetailOverview() {
|
export default function ServerDetailOverview() {
|
||||||
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const { lastMessage, readyState } = useWebSocketContext();
|
const { lastMessage, readyState } = useWebSocketContext();
|
||||||
|
|
||||||
// 检查连接状态
|
|
||||||
if (readyState !== 1) {
|
if (readyState !== 1) {
|
||||||
return <ServerDetailLoading />;
|
return <ServerDetailLoading />;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析消息
|
|
||||||
const nezhaWsData = lastMessage
|
const nezhaWsData = lastMessage
|
||||||
? (JSON.parse(lastMessage.data) as NezhaAPIResponse)
|
? (JSON.parse(lastMessage.data) as NezhaAPIResponse)
|
||||||
: null;
|
: null;
|
||||||
@ -48,7 +48,9 @@ export default function ServerDetailOverview() {
|
|||||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||||
<CardContent className="px-1.5 py-1">
|
<CardContent className="px-1.5 py-1">
|
||||||
<section className="flex flex-col items-start gap-0.5">
|
<section className="flex flex-col items-start gap-0.5">
|
||||||
<p className="text-xs text-muted-foreground">{"Status"}</p>
|
<p className="text-xs text-muted-foreground">
|
||||||
|
{t("serverDetail.status")}
|
||||||
|
</p>
|
||||||
<Badge
|
<Badge
|
||||||
className={cn(
|
className={cn(
|
||||||
"text-[9px] rounded-[6px] w-fit px-1 py-0 -mt-[0.3px] dark:text-white",
|
"text-[9px] rounded-[6px] w-fit px-1 py-0 -mt-[0.3px] dark:text-white",
|
||||||
@ -58,7 +60,7 @@ export default function ServerDetailOverview() {
|
|||||||
},
|
},
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{online ? "Online" : "Offline"}
|
{online ? t("serverDetail.online") : t("serverDetail.offline")}
|
||||||
</Badge>
|
</Badge>
|
||||||
</section>
|
</section>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
@ -66,7 +68,9 @@ export default function ServerDetailOverview() {
|
|||||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||||
<CardContent className="px-1.5 py-1">
|
<CardContent className="px-1.5 py-1">
|
||||||
<section className="flex flex-col items-start gap-0.5">
|
<section className="flex flex-col items-start gap-0.5">
|
||||||
<p className="text-xs text-muted-foreground">{"Uptime"}</p>
|
<p className="text-xs text-muted-foreground">
|
||||||
|
{t("serverDetail.uptime")}
|
||||||
|
</p>
|
||||||
<div className="text-xs">
|
<div className="text-xs">
|
||||||
{" "}
|
{" "}
|
||||||
{online ? (uptime / 86400).toFixed(0) : "N/A"} {"Days"}{" "}
|
{online ? (uptime / 86400).toFixed(0) : "N/A"} {"Days"}{" "}
|
||||||
@ -77,23 +81,33 @@ export default function ServerDetailOverview() {
|
|||||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||||
<CardContent className="px-1.5 py-1">
|
<CardContent className="px-1.5 py-1">
|
||||||
<section className="flex flex-col items-start gap-0.5">
|
<section className="flex flex-col items-start gap-0.5">
|
||||||
<p className="text-xs text-muted-foreground">{"Version"}</p>
|
<p className="text-xs text-muted-foreground">
|
||||||
<div className="text-xs">{version || "Unknown"} </div>
|
{t("serverDetail.version")}
|
||||||
|
</p>
|
||||||
|
<div className="text-xs">
|
||||||
|
{version || t("serverDetail.unknown")}{" "}
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||||
<CardContent className="px-1.5 py-1">
|
<CardContent className="px-1.5 py-1">
|
||||||
<section className="flex flex-col items-start gap-0.5">
|
<section className="flex flex-col items-start gap-0.5">
|
||||||
<p className="text-xs text-muted-foreground">{"Arch"}</p>
|
<p className="text-xs text-muted-foreground">
|
||||||
<div className="text-xs">{server.host.arch || "Unknown"} </div>
|
{t("serverDetail.arch")}
|
||||||
|
</p>
|
||||||
|
<div className="text-xs">
|
||||||
|
{server.host.arch || t("serverDetail.unknown")}{" "}
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||||
<CardContent className="px-1.5 py-1">
|
<CardContent className="px-1.5 py-1">
|
||||||
<section className="flex flex-col items-start gap-0.5">
|
<section className="flex flex-col items-start gap-0.5">
|
||||||
<p className="text-xs text-muted-foreground">{"Mem"}</p>
|
<p className="text-xs text-muted-foreground">
|
||||||
|
{t("serverDetail.mem")}
|
||||||
|
</p>
|
||||||
<div className="text-xs">
|
<div className="text-xs">
|
||||||
{formatBytes(server.host.mem_total)}
|
{formatBytes(server.host.mem_total)}
|
||||||
</div>
|
</div>
|
||||||
@ -103,7 +117,9 @@ export default function ServerDetailOverview() {
|
|||||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||||
<CardContent className="px-1.5 py-1">
|
<CardContent className="px-1.5 py-1">
|
||||||
<section className="flex flex-col items-start gap-0.5">
|
<section className="flex flex-col items-start gap-0.5">
|
||||||
<p className="text-xs text-muted-foreground">{"Disk"}</p>
|
<p className="text-xs text-muted-foreground">
|
||||||
|
{t("serverDetail.disk")}
|
||||||
|
</p>
|
||||||
<div className="text-xs">
|
<div className="text-xs">
|
||||||
{formatBytes(server.host.disk_total)}
|
{formatBytes(server.host.disk_total)}
|
||||||
</div>
|
</div>
|
||||||
@ -113,10 +129,13 @@ export default function ServerDetailOverview() {
|
|||||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||||
<CardContent className="px-1.5 py-1">
|
<CardContent className="px-1.5 py-1">
|
||||||
<section className="flex flex-col items-start gap-0.5">
|
<section className="flex flex-col items-start gap-0.5">
|
||||||
<p className="text-xs text-muted-foreground">{"Region"}</p>
|
<p className="text-xs text-muted-foreground">
|
||||||
|
{t("serverDetail.region")}
|
||||||
|
</p>
|
||||||
<section className="flex items-start gap-1">
|
<section className="flex items-start gap-1">
|
||||||
<div className="text-xs text-start">
|
<div className="text-xs text-start">
|
||||||
{server.host.country_code?.toUpperCase() || "Unknown"}
|
{server.host.country_code?.toUpperCase() ||
|
||||||
|
t("serverDetail.unknown")}
|
||||||
</div>
|
</div>
|
||||||
{server.host.country_code && (
|
{server.host.country_code && (
|
||||||
<ServerFlag
|
<ServerFlag
|
||||||
@ -133,15 +152,17 @@ export default function ServerDetailOverview() {
|
|||||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||||
<CardContent className="px-1.5 py-1">
|
<CardContent className="px-1.5 py-1">
|
||||||
<section className="flex flex-col items-start gap-0.5">
|
<section className="flex flex-col items-start gap-0.5">
|
||||||
<p className="text-xs text-muted-foreground">{"System"}</p>
|
<p className="text-xs text-muted-foreground">
|
||||||
|
{t("serverDetail.system")}
|
||||||
|
</p>
|
||||||
{server.host.platform ? (
|
{server.host.platform ? (
|
||||||
<div className="text-xs">
|
<div className="text-xs">
|
||||||
{" "}
|
{" "}
|
||||||
{server.host.platform || "Unknown"} -{" "}
|
{server.host.platform || t("serverDetail.unknown")} -{" "}
|
||||||
{server.host.platform_version}{" "}
|
{server.host.platform_version}{" "}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-xs">Unknown</div>
|
<div className="text-xs"> {t("serverDetail.unknown")}</div>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
@ -153,7 +174,7 @@ export default function ServerDetailOverview() {
|
|||||||
{server.host.cpu ? (
|
{server.host.cpu ? (
|
||||||
<div className="text-xs"> {server.host.cpu}</div>
|
<div className="text-xs"> {server.host.cpu}</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-xs">Unknown</div>
|
<div className="text-xs"> {t("serverDetail.unknown")}</div>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { cn, formatBytes } from "@/lib/utils";
|
import { cn, formatBytes } from "@/lib/utils";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
type ServerOverviewProps = {
|
type ServerOverviewProps = {
|
||||||
online: number;
|
online: number;
|
||||||
@ -16,6 +17,8 @@ export default function ServerOverview({
|
|||||||
up,
|
up,
|
||||||
down,
|
down,
|
||||||
}: ServerOverviewProps) {
|
}: ServerOverviewProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className="grid grid-cols-2 gap-4 lg:grid-cols-4">
|
<section className="grid grid-cols-2 gap-4 lg:grid-cols-4">
|
||||||
@ -23,7 +26,7 @@ export default function ServerOverview({
|
|||||||
<CardContent className="px-6 py-3">
|
<CardContent className="px-6 py-3">
|
||||||
<section className="flex flex-col gap-1">
|
<section className="flex flex-col gap-1">
|
||||||
<p className="text-sm font-medium md:text-base">
|
<p className="text-sm font-medium md:text-base">
|
||||||
{"Total servers"}
|
{t("serverOverview.totalServers")}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="relative flex h-2 w-2">
|
<span className="relative flex h-2 w-2">
|
||||||
@ -42,7 +45,7 @@ export default function ServerOverview({
|
|||||||
<CardContent className="px-6 py-3">
|
<CardContent className="px-6 py-3">
|
||||||
<section className="flex flex-col gap-1">
|
<section className="flex flex-col gap-1">
|
||||||
<p className="text-sm font-medium md:text-base">
|
<p className="text-sm font-medium md:text-base">
|
||||||
{"Online servers"}
|
{t("serverOverview.onlineServers")}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="relative flex h-2 w-2">
|
<span className="relative flex h-2 w-2">
|
||||||
@ -63,7 +66,7 @@ export default function ServerOverview({
|
|||||||
<CardContent className="px-6 py-3">
|
<CardContent className="px-6 py-3">
|
||||||
<section className="flex flex-col gap-1">
|
<section className="flex flex-col gap-1">
|
||||||
<p className="text-sm font-medium md:text-base">
|
<p className="text-sm font-medium md:text-base">
|
||||||
{"Offline servers"}
|
{t("serverOverview.offlineServers")}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="relative flex h-2 w-2">
|
<span className="relative flex h-2 w-2">
|
||||||
@ -83,7 +86,7 @@ export default function ServerOverview({
|
|||||||
<CardContent className="relative px-6 py-3">
|
<CardContent className="relative px-6 py-3">
|
||||||
<section className="flex flex-col gap-1">
|
<section className="flex flex-col gap-1">
|
||||||
<p className="text-sm font-medium md:text-base">
|
<p className="text-sm font-medium md:text-base">
|
||||||
{"Total bandwidth"}
|
{t("serverOverview.totalBandwidth")}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<section className="flex flex-col sm:flex-row pt-[8px] sm:items-center items-start gap-1">
|
<section className="flex flex-col sm:flex-row pt-[8px] sm:items-center items-start gap-1">
|
||||||
|
@ -1,5 +1,35 @@
|
|||||||
{
|
{
|
||||||
|
"nezha": "Nezha Monitoring",
|
||||||
"overview": "Overview",
|
"overview": "Overview",
|
||||||
|
"whereTheTimeIs": "Where the time is",
|
||||||
|
"serverOverview": {
|
||||||
|
"totalServers": "Total Servers",
|
||||||
|
"onlineServers": "Online Servers",
|
||||||
|
"offlineServers": "Offline Servers",
|
||||||
|
"totalBandwidth": "Total Bandwidth"
|
||||||
|
},
|
||||||
|
"serverCard": {
|
||||||
|
"mem": "MEM",
|
||||||
|
"stg": "STG",
|
||||||
|
"upload": "Upload",
|
||||||
|
"download": "Download"
|
||||||
|
},
|
||||||
|
"serverDetail": {
|
||||||
|
"status": "Status",
|
||||||
|
"online": "Online",
|
||||||
|
"offline": "Offline",
|
||||||
|
"unknown": "Unknown",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"version": "Version",
|
||||||
|
"arch": "Arch",
|
||||||
|
"mem": "Mem",
|
||||||
|
"disk": "Disk",
|
||||||
|
"region": "Region",
|
||||||
|
"system": "System"
|
||||||
|
},
|
||||||
|
"footer": {
|
||||||
|
"themeBy": "Theme by "
|
||||||
|
},
|
||||||
"language": {
|
"language": {
|
||||||
"zh-CN": "简体中文",
|
"zh-CN": "简体中文",
|
||||||
"zh-TW": "繁體中文",
|
"zh-TW": "繁體中文",
|
||||||
|
@ -1,5 +1,35 @@
|
|||||||
{
|
{
|
||||||
|
"nezha": "哪吒监控",
|
||||||
"overview": "概览",
|
"overview": "概览",
|
||||||
|
"whereTheTimeIs": "当前时间",
|
||||||
|
"serverOverview": {
|
||||||
|
"totalServers": "服务器总数",
|
||||||
|
"onlineServers": "在线服务器",
|
||||||
|
"offlineServers": "离线服务器",
|
||||||
|
"totalBandwidth": "总流量"
|
||||||
|
},
|
||||||
|
"serverCard": {
|
||||||
|
"mem": "内存",
|
||||||
|
"stg": "存储",
|
||||||
|
"upload": "上传",
|
||||||
|
"download": "下载"
|
||||||
|
},
|
||||||
|
"serverDetail": {
|
||||||
|
"status": "状态",
|
||||||
|
"online": "在线",
|
||||||
|
"offline": "离线",
|
||||||
|
"unknown": "未知",
|
||||||
|
"uptime": "运行时间",
|
||||||
|
"version": "版本",
|
||||||
|
"arch": "架构",
|
||||||
|
"mem": "内存",
|
||||||
|
"disk": "磁盘",
|
||||||
|
"region": "区域",
|
||||||
|
"system": "系统"
|
||||||
|
},
|
||||||
|
"footer": {
|
||||||
|
"themeBy": "主题-"
|
||||||
|
},
|
||||||
"language": {
|
"language": {
|
||||||
"zh-CN": "简体中文",
|
"zh-CN": "简体中文",
|
||||||
"zh-TW": "繁體中文",
|
"zh-TW": "繁體中文",
|
||||||
|
@ -1,5 +1,35 @@
|
|||||||
{
|
{
|
||||||
|
"nezha": "哪吒監控",
|
||||||
"overview": "概覽",
|
"overview": "概覽",
|
||||||
|
"whereTheTimeIs": "目前時間",
|
||||||
|
"serverOverview": {
|
||||||
|
"totalServers": "總服務器",
|
||||||
|
"onlineServers": "線上服務器",
|
||||||
|
"offlineServers": "離線服務器",
|
||||||
|
"totalBandwidth": "總帶寬"
|
||||||
|
},
|
||||||
|
"serverCard": {
|
||||||
|
"mem": "內存",
|
||||||
|
"stg": "存儲",
|
||||||
|
"upload": "上傳",
|
||||||
|
"download": "下載"
|
||||||
|
},
|
||||||
|
"serverDetail": {
|
||||||
|
"status": "狀態",
|
||||||
|
"online": "線上",
|
||||||
|
"offline": "離線",
|
||||||
|
"unknown": "未知",
|
||||||
|
"uptime": "運行時間",
|
||||||
|
"version": "版本",
|
||||||
|
"arch": "架構",
|
||||||
|
"mem": "內存",
|
||||||
|
"disk": "磁盤",
|
||||||
|
"region": "地區",
|
||||||
|
"system": "系統"
|
||||||
|
},
|
||||||
|
"footer": {
|
||||||
|
"themeBy": "主題-"
|
||||||
|
},
|
||||||
"language": {
|
"language": {
|
||||||
"zh-CN": "简体中文",
|
"zh-CN": "简体中文",
|
||||||
"zh-TW": "繁體中文",
|
"zh-TW": "繁體中文",
|
||||||
@ -8,6 +38,6 @@
|
|||||||
"theme": {
|
"theme": {
|
||||||
"light": "亮色",
|
"light": "亮色",
|
||||||
"dark": "暗色",
|
"dark": "暗色",
|
||||||
"system": "跟随系統"
|
"system": "跟隨系統"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,8 @@ export default function Servers() {
|
|||||||
});
|
});
|
||||||
const { lastMessage, readyState } = useWebSocketContext();
|
const { lastMessage, readyState } = useWebSocketContext();
|
||||||
|
|
||||||
// 添加分组状态
|
|
||||||
const [currentGroup, setCurrentGroup] = useState<string>("All");
|
const [currentGroup, setCurrentGroup] = useState<string>("All");
|
||||||
|
|
||||||
// 获取所有分组名称
|
|
||||||
const groupTabs = [
|
const groupTabs = [
|
||||||
"All",
|
"All",
|
||||||
...(groupData?.data?.map((item: ServerGroup) => item.group.name) || []),
|
...(groupData?.data?.map((item: ServerGroup) => item.group.name) || []),
|
||||||
@ -32,7 +30,6 @@ export default function Servers() {
|
|||||||
}
|
}
|
||||||
}, [readyState]);
|
}, [readyState]);
|
||||||
|
|
||||||
// 检查连接状态
|
|
||||||
if (readyState !== 1) {
|
if (readyState !== 1) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center justify-center ">
|
<div className="flex flex-col items-center justify-center ">
|
||||||
@ -41,7 +38,6 @@ export default function Servers() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析消息
|
|
||||||
const nezhaWsData = lastMessage
|
const nezhaWsData = lastMessage
|
||||||
? (JSON.parse(lastMessage.data) as NezhaAPIResponse)
|
? (JSON.parse(lastMessage.data) as NezhaAPIResponse)
|
||||||
: null;
|
: null;
|
||||||
@ -54,7 +50,6 @@ export default function Servers() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算所有服务器的统计数据(用于 Overview)
|
|
||||||
const totalServers = nezhaWsData?.servers?.length || 0;
|
const totalServers = nezhaWsData?.servers?.length || 0;
|
||||||
const onlineServers =
|
const onlineServers =
|
||||||
nezhaWsData?.servers?.filter((server) => formatNezhaInfo(server).online)
|
nezhaWsData?.servers?.filter((server) => formatNezhaInfo(server).online)
|
||||||
@ -73,7 +68,6 @@ export default function Servers() {
|
|||||||
0,
|
0,
|
||||||
) || 0;
|
) || 0;
|
||||||
|
|
||||||
// 根据当前选中的分组筛选服务器(用于显示列表)
|
|
||||||
const filteredServers =
|
const filteredServers =
|
||||||
nezhaWsData?.servers?.filter((server) => {
|
nezhaWsData?.servers?.filter((server) => {
|
||||||
if (currentGroup === "All") return true;
|
if (currentGroup === "All") return true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user