feat: net transfer badge

This commit is contained in:
hamster1963 2024-11-30 22:26:13 +08:00
parent 48b2d1493a
commit 3f0c2ed39d
8 changed files with 61 additions and 48 deletions

View File

@ -11,9 +11,7 @@ export default function GroupSwitch({
setCurrentTab: (tab: string) => void; setCurrentTab: (tab: string) => void;
}) { }) {
return ( return (
<div <div className="scrollbar-hidden z-50 flex flex-col items-start overflow-x-scroll rounded-[50px]">
className="scrollbar-hidden z-50 flex flex-col items-start overflow-x-scroll rounded-[50px]"
>
<div className="flex items-center gap-1 rounded-[50px] bg-stone-100 p-[3px] dark:bg-stone-800"> <div className="flex items-center gap-1 rounded-[50px] bg-stone-100 p-[3px] dark:bg-stone-800">
{tabs.map((tab: string) => ( {tabs.map((tab: string) => (
<div <div

View File

@ -6,6 +6,8 @@ import { NezhaServer } 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"; import { useTranslation } from "react-i18next";
import { Badge } from "./ui/badge";
import { formatBytes } from "@/lib/format";
export default function ServerCard({ export default function ServerCard({
now, now,
@ -101,6 +103,20 @@ export default function ServerCard({
</div> </div>
</div> </div>
</section> </section>
<section className={"flex items-center justify-between gap-1"}>
<Badge
variant="secondary"
className="items-center flex-1 justify-center rounded-[8px] text-nowrap text-[11px] border-muted-50 shadow-md shadow-neutral-200/30 dark:shadow-none"
>
{t("Upload")}:{formatBytes(serverInfo.state.net_out_transfer)}
</Badge>
<Badge
variant="outline"
className="items-center flex-1 justify-center rounded-[8px] text-nowrap text-[11px] shadow-md shadow-neutral-200/30 dark:shadow-none"
>
{t("Download")}:{formatBytes(serverInfo.state.net_in_transfer)}
</Badge>
</section>
</div> </div>
</Card> </Card>
</section> </section>

View File

@ -4,10 +4,11 @@ import ServerFlag from "@/components/ServerFlag";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { Card, CardContent } from "@/components/ui/card"; import { Card, CardContent } from "@/components/ui/card";
import { useWebSocketContext } from "@/hooks/use-websocket-context"; import { useWebSocketContext } from "@/hooks/use-websocket-context";
import { cn, formatBytes, formatNezhaInfo } from "@/lib/utils"; import { cn, formatNezhaInfo } from "@/lib/utils";
import { NezhaWebsocketResponse } from "@/types/nezha-api"; import { NezhaWebsocketResponse } from "@/types/nezha-api";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { formatBytes } from "@/lib/format";
export default function ServerDetailOverview({ export default function ServerDetailOverview({
server_id, server_id,
@ -37,7 +38,10 @@ export default function ServerDetailOverview({
return <ServerDetailLoading />; return <ServerDetailLoading />;
} }
const { name, online, uptime, version } = formatNezhaInfo(nezhaWsData.now,server); const { name, online, uptime, version } = formatNezhaInfo(
nezhaWsData.now,
server,
);
return ( return (
<div> <div>

View File

@ -1,6 +1,7 @@
import { Card, CardContent } from "@/components/ui/card"; import { Card, CardContent } from "@/components/ui/card";
import { cn, formatBytes } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { formatBytes } from "@/lib/format";
type ServerOverviewProps = { type ServerOverviewProps = {
online: number; online: number;

View File

@ -1,9 +1,19 @@
export function formatBytes(bytes: number, decimals = 2): string { export function formatBytes(bytes: number, decimals: number = 2) {
if (bytes === 0) return "0 B"; if (!+bytes) return "0 Bytes";
const k = 1024; const k = 1024;
const dm = decimals < 0 ? 0 : decimals; const dm = decimals < 0 ? 0 : decimals;
const sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; const sizes = [
"Bytes",
"KiB",
"MiB",
"GiB",
"TiB",
"PiB",
"EiB",
"ZiB",
"YiB",
];
const i = Math.floor(Math.log(bytes) / Math.log(k)); const i = Math.floor(Math.log(bytes) / Math.log(k));

View File

@ -27,28 +27,6 @@ export function formatNezhaInfo(now: number,serverInfo: NezhaServer) {
}; };
} }
export function formatBytes(bytes: number, decimals: number = 2) {
if (!+bytes) return "0 Bytes";
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = [
"Bytes",
"KiB",
"MiB",
"GiB",
"TiB",
"PiB",
"EiB",
"ZiB",
"YiB",
];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
}
export function getDaysBetweenDates(date1: string, date2: string): number { export function getDaysBetweenDates(date1: string, date2: string): number {
const oneDay = 24 * 60 * 60 * 1000; // 一天的毫秒数 const oneDay = 24 * 60 * 60 * 1000; // 一天的毫秒数
const firstDate = new Date(date1); const firstDate = new Date(date1);

View File

@ -57,11 +57,13 @@ export default function Servers() {
const totalServers = nezhaWsData?.servers?.length || 0; const totalServers = nezhaWsData?.servers?.length || 0;
const onlineServers = const onlineServers =
nezhaWsData?.servers?.filter((server) => formatNezhaInfo(nezhaWsData.now,server).online) nezhaWsData?.servers?.filter(
?.length || 0; (server) => formatNezhaInfo(nezhaWsData.now, server).online,
)?.length || 0;
const offlineServers = const offlineServers =
nezhaWsData?.servers?.filter((server) => !formatNezhaInfo(nezhaWsData.now,server).online) nezhaWsData?.servers?.filter(
?.length || 0; (server) => !formatNezhaInfo(nezhaWsData.now, server).online,
)?.length || 0;
const up = const up =
nezhaWsData?.servers?.reduce( nezhaWsData?.servers?.reduce(
(total, server) => total + server.state.net_out_transfer, (total, server) => total + server.state.net_out_transfer,
@ -112,7 +114,11 @@ export default function Servers() {
{showServices && <ServiceTracker />} {showServices && <ServiceTracker />}
<section className="grid grid-cols-1 gap-2 md:grid-cols-2 mt-6"> <section className="grid grid-cols-1 gap-2 md:grid-cols-2 mt-6">
{filteredServers.map((serverInfo) => ( {filteredServers.map((serverInfo) => (
<ServerCard now={nezhaWsData.now} key={serverInfo.id} serverInfo={serverInfo} /> <ServerCard
now={nezhaWsData.now}
key={serverInfo.id}
serverInfo={serverInfo}
/>
))} ))}
</section> </section>
</div> </div>