mirror of
https://github.com/woodchen-ink/nezha-dash-v1.git
synced 2025-07-18 17:41:56 +08:00
feat(note): endDate info
This commit is contained in:
parent
e780521b0b
commit
91677dfd90
@ -1,7 +1,12 @@
|
||||
import ServerFlag from "@/components/ServerFlag";
|
||||
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 { Card } from "./ui/card";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
@ -29,10 +34,27 @@ export default function ServerCard({
|
||||
stg,
|
||||
net_in_transfer,
|
||||
net_out_transfer,
|
||||
public_note,
|
||||
} = formatNezhaInfo(now, serverInfo);
|
||||
|
||||
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 ? (
|
||||
<section>
|
||||
<Card
|
||||
@ -54,7 +76,7 @@ export default function ServerCard({
|
||||
>
|
||||
{showFlag ? <ServerFlag country_code={country_code} /> : null}
|
||||
</div>
|
||||
<div className="relative">
|
||||
<div className="relative flex flex-col">
|
||||
<p
|
||||
className={cn(
|
||||
"break-all font-bold tracking-tight",
|
||||
@ -63,6 +85,20 @@ export default function ServerCard({
|
||||
>
|
||||
{name}
|
||||
</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>
|
||||
</section>
|
||||
<div className="flex flex-col gap-2">
|
||||
@ -135,7 +171,7 @@ export default function ServerCard({
|
||||
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",
|
||||
)}
|
||||
onClick={() => navigate(`/server/${serverInfo.id}`)}
|
||||
onClick={() => navigate(`/server/${serverInfo.id}`, { replace: true })}
|
||||
>
|
||||
<section
|
||||
className={cn("grid items-center gap-2 lg:w-40")}
|
||||
|
@ -38,6 +38,7 @@ export function formatNezhaInfo(now: number, serverInfo: NezhaServer) {
|
||||
load_1: serverInfo.state.load_1?.toFixed(2) || 0.0,
|
||||
load_5: serverInfo.state.load_5?.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);
|
||||
|
||||
// 计算两个日期之间的天数差异
|
||||
return Math.round(
|
||||
Math.abs((firstDate.getTime() - secondDate.getTime()) / oneDay),
|
||||
);
|
||||
return Math.round((firstDate.getTime() - secondDate.getTime()) / oneDay);
|
||||
}
|
||||
|
||||
export const fetcher = (url: string) =>
|
||||
@ -115,3 +114,73 @@ export function formatTime(timestamp: number): string {
|
||||
const seconds = date.getSeconds().toString().padStart(2, "0");
|
||||
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 "";
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ export interface NezhaWebsocketResponse {
|
||||
export interface NezhaServer {
|
||||
id: number;
|
||||
name: string;
|
||||
public_note: string;
|
||||
last_active: string;
|
||||
country_code: string;
|
||||
host: NezhaServerHost;
|
||||
|
Loading…
x
Reference in New Issue
Block a user