feat(note): endDate info

This commit is contained in:
hamster1963 2024-12-02 16:08:41 +08:00
parent e780521b0b
commit 91677dfd90
3 changed files with 112 additions and 6 deletions

View File

@ -1,7 +1,12 @@
import ServerFlag from "@/components/ServerFlag"; import ServerFlag from "@/components/ServerFlag";
import ServerUsageBar from "@/components/ServerUsageBar"; import ServerUsageBar from "@/components/ServerUsageBar";
import { cn, formatNezhaInfo } from "@/lib/utils"; import {
cn,
formatNezhaInfo,
parsePublicNote,
getDaysBetweenDates,
} from "@/lib/utils";
import { NezhaServer } from "@/types/nezha-api"; 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";
@ -29,10 +34,27 @@ export default function ServerCard({
stg, stg,
net_in_transfer, net_in_transfer,
net_out_transfer, net_out_transfer,
public_note,
} = formatNezhaInfo(now, serverInfo); } = formatNezhaInfo(now, serverInfo);
const showFlag = true; const showFlag = true;
const parsedData = parsePublicNote(public_note);
let daysLeft = 0;
let isNeverExpire = false;
if (parsedData?.billingDataMod?.endDate) {
if (parsedData.billingDataMod.endDate.startsWith("0000-00-00")) {
isNeverExpire = true;
} else {
daysLeft = getDaysBetweenDates(
parsedData.billingDataMod.endDate,
new Date().toISOString(),
);
}
}
return online ? ( return online ? (
<section> <section>
<Card <Card
@ -54,7 +76,7 @@ export default function ServerCard({
> >
{showFlag ? <ServerFlag country_code={country_code} /> : null} {showFlag ? <ServerFlag country_code={country_code} /> : null}
</div> </div>
<div className="relative"> <div className="relative flex flex-col">
<p <p
className={cn( className={cn(
"break-all font-bold tracking-tight", "break-all font-bold tracking-tight",
@ -63,6 +85,20 @@ export default function ServerCard({
> >
{name} {name}
</p> </p>
{parsedData &&
(daysLeft >= 0 ? (
<p className={cn("text-[10px] text-muted-foreground")}>
: {isNeverExpire ? "永久" : daysLeft + "天"}
</p>
) : (
<p
className={cn(
"text-[10px] text-muted-foreground text-red-600",
)}
>
: {daysLeft * -1}
</p>
))}
</div> </div>
</section> </section>
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
@ -135,7 +171,7 @@ export default function ServerCard({
className={cn( className={cn(
"flex flex-col lg:min-h-[91px] min-h-[123px] items-center justify-start gap-3 p-3 md:px-5 lg:flex-row cursor-pointer hover:bg-accent/50 transition-colors", "flex flex-col lg:min-h-[91px] min-h-[123px] items-center justify-start gap-3 p-3 md:px-5 lg:flex-row cursor-pointer hover:bg-accent/50 transition-colors",
)} )}
onClick={() => navigate(`/server/${serverInfo.id}`)} onClick={() => navigate(`/server/${serverInfo.id}`, { replace: true })}
> >
<section <section
className={cn("grid items-center gap-2 lg:w-40")} className={cn("grid items-center gap-2 lg:w-40")}

View File

@ -38,6 +38,7 @@ export function formatNezhaInfo(now: number, serverInfo: NezhaServer) {
load_1: serverInfo.state.load_1?.toFixed(2) || 0.0, load_1: serverInfo.state.load_1?.toFixed(2) || 0.0,
load_5: serverInfo.state.load_5?.toFixed(2) || 0.0, load_5: serverInfo.state.load_5?.toFixed(2) || 0.0,
load_15: serverInfo.state.load_15?.toFixed(2) || 0.0, load_15: serverInfo.state.load_15?.toFixed(2) || 0.0,
public_note: handlePublicNote(serverInfo.id, serverInfo.public_note || ""),
}; };
} }
@ -47,9 +48,7 @@ export function getDaysBetweenDates(date1: string, date2: string): number {
const secondDate = new Date(date2); const secondDate = new Date(date2);
// 计算两个日期之间的天数差异 // 计算两个日期之间的天数差异
return Math.round( return Math.round((firstDate.getTime() - secondDate.getTime()) / oneDay);
Math.abs((firstDate.getTime() - secondDate.getTime()) / oneDay),
);
} }
export const fetcher = (url: string) => export const fetcher = (url: string) =>
@ -115,3 +114,73 @@ export function formatTime(timestamp: number): string {
const seconds = date.getSeconds().toString().padStart(2, "0"); const seconds = date.getSeconds().toString().padStart(2, "0");
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
} }
interface BillingData {
startDate: string;
endDate: string;
autoRenewal: string;
cycle: string;
amount: string;
}
interface PlanData {
bandwidth: string;
trafficVol: string;
trafficType: string;
IPv4: string;
IPv6: string;
networkRoute: string;
extra: string;
}
interface PublicNoteData {
billingDataMod: BillingData;
planDataMod: PlanData;
}
export function parsePublicNote(publicNote: string): PublicNoteData | null {
try {
if (!publicNote) {
return null;
}
const data = JSON.parse(publicNote);
return {
billingDataMod: {
startDate: data.billingDataMod.startDate,
endDate: data.billingDataMod.endDate,
autoRenewal: data.billingDataMod.autoRenewal,
cycle: data.billingDataMod.cycle,
amount: data.billingDataMod.amount,
},
planDataMod: {
bandwidth: data.planDataMod.bandwidth,
trafficVol: data.planDataMod.trafficVol,
trafficType: data.planDataMod.trafficType,
IPv4: data.planDataMod.IPv4,
IPv6: data.planDataMod.IPv6,
networkRoute: data.planDataMod.networkRoute,
extra: data.planDataMod.extra,
},
};
} catch (error) {
console.error("Error parsing public note:", error);
return null;
}
}
// Function to handle public_note with sessionStorage
export function handlePublicNote(serverId: number, publicNote: string): string {
const storageKey = `server_${serverId}_public_note`;
const storedNote = sessionStorage.getItem(storageKey);
if (!publicNote && storedNote) {
return storedNote;
}
if (publicNote) {
sessionStorage.setItem(storageKey, publicNote);
return publicNote;
}
return "";
}

View File

@ -6,6 +6,7 @@ export interface NezhaWebsocketResponse {
export interface NezhaServer { export interface NezhaServer {
id: number; id: number;
name: string; name: string;
public_note: string;
last_active: string; last_active: string;
country_code: string; country_code: string;
host: NezhaServerHost; host: NezhaServerHost;