mirror of
https://github.com/hamster1963/nezha-dash.git
synced 2025-04-24 21:10:45 +08:00
Merge branch 'main' into cloudflare
This commit is contained in:
commit
1976bce1c4
@ -16,7 +16,7 @@
|
|||||||
| ------------------------------ | ------------------------ | ------------------------------------------------------------- |
|
| ------------------------------ | ------------------------ | ------------------------------------------------------------- |
|
||||||
| NezhaBaseUrl | nezha 面板地址 | http://120.x.x.x:8008 |
|
| NezhaBaseUrl | nezha 面板地址 | http://120.x.x.x:8008 |
|
||||||
| NezhaAuth | nezha 面板 API Token | 5hAY3QX6Nl9B3Uxxxx26KMvOMyXS1Udi |
|
| NezhaAuth | nezha 面板 API Token | 5hAY3QX6Nl9B3Uxxxx26KMvOMyXS1Udi |
|
||||||
| SitePassword | 页面密码 | 123456 |
|
| SitePassword | 页面密码 | **默认**:无密码 |
|
||||||
| DefaultLocale | 面板默认显示语言 | **默认**:en [简中:zh 繁中:zh-t 英语:en 日语:ja] |
|
| DefaultLocale | 面板默认显示语言 | **默认**:en [简中:zh 繁中:zh-t 英语:en 日语:ja] |
|
||||||
| ForceShowAllServers | 是否强制显示所有服务器 | **默认**:false |
|
| ForceShowAllServers | 是否强制显示所有服务器 | **默认**:false |
|
||||||
| NEXT_PUBLIC_NezhaFetchInterval | 获取数据间隔(毫秒) | **默认**:2000 |
|
| NEXT_PUBLIC_NezhaFetchInterval | 获取数据间隔(毫秒) | **默认**:2000 |
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
import { ServerDetailLoading } from "@/app/[locale]/(main)/ClientComponents/ServerDetailLoading";
|
import { ServerDetailLoading } from "@/app/[locale]/(main)/ClientComponents/ServerDetailLoading";
|
||||||
import { NezhaAPISafe } from "@/app/[locale]/types/nezha-api";
|
import { NezhaAPISafe } from "@/app/[locale]/types/nezha-api";
|
||||||
import { BackIcon } from "@/components/Icon";
|
import { BackIcon } from "@/components/Icon";
|
||||||
|
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 getEnv from "@/lib/env-entry";
|
import getEnv from "@/lib/env-entry";
|
||||||
@ -60,7 +61,7 @@ export default function ServerDetailClient({
|
|||||||
<p className="text-xs text-muted-foreground">{t("status")}</p>
|
<p className="text-xs text-muted-foreground">{t("status")}</p>
|
||||||
<Badge
|
<Badge
|
||||||
className={cn(
|
className={cn(
|
||||||
"text-[10px] rounded-[6px] w-fit px-1 py-0 dark:text-white",
|
"text-[9px] rounded-[6px] w-fit px-1 py-0 -mt-[0.3px] dark:text-white",
|
||||||
{
|
{
|
||||||
" bg-green-800": data?.online_status,
|
" bg-green-800": data?.online_status,
|
||||||
" bg-red-600": !data?.online_status,
|
" bg-red-600": !data?.online_status,
|
||||||
@ -115,6 +116,22 @@ export default function ServerDetailClient({
|
|||||||
</section>
|
</section>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||||
|
<CardContent className="px-1.5 py-1">
|
||||||
|
<section className="flex flex-col items-start gap-0.5">
|
||||||
|
<p className="text-xs text-muted-foreground">{t("Region")}</p>
|
||||||
|
<section className="flex items-start gap-1">
|
||||||
|
<div className="text-xs text-start">
|
||||||
|
{data?.host.CountryCode.toUpperCase()}
|
||||||
|
</div>
|
||||||
|
<ServerFlag
|
||||||
|
className="text-[11px] -mt-[1px]"
|
||||||
|
country_code={data?.host.CountryCode}
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
</section>
|
</section>
|
||||||
<section className="flex flex-wrap gap-2 mt-1">
|
<section className="flex flex-wrap gap-2 mt-1">
|
||||||
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
<Card className="rounded-[10px] bg-transparent border-none shadow-none">
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
// @auto-i18n-check. Please do not delete the line.
|
// @auto-i18n-check. Please do not delete the line.
|
||||||
import { auth } from "@/auth";
|
|
||||||
import { locales } from "@/i18n-metadata";
|
import { locales } from "@/i18n-metadata";
|
||||||
import getEnv from "@/lib/env-entry";
|
import getEnv from "@/lib/env-entry";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
@ -13,8 +12,6 @@ import { ThemeProvider } from "next-themes";
|
|||||||
import { Inter as FontSans } from "next/font/google";
|
import { Inter as FontSans } from "next/font/google";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import "/node_modules/flag-icons/css/flag-icons.min.css";
|
|
||||||
|
|
||||||
const fontSans = FontSans({
|
const fontSans = FontSans({
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
variable: "--font-sans",
|
variable: "--font-sans",
|
||||||
@ -65,6 +62,10 @@ export default function LocaleLayout({
|
|||||||
<html lang={locale} suppressHydrationWarning>
|
<html lang={locale} suppressHydrationWarning>
|
||||||
<head>
|
<head>
|
||||||
<PublicEnvScript />
|
<PublicEnvScript />
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://cdn.jsdelivr.net/gh/lipis/flag-icons@7.0.0/css/flag-icons.min.css"
|
||||||
|
/>
|
||||||
</head>
|
</head>
|
||||||
<body
|
<body
|
||||||
className={cn(
|
className={cn(
|
||||||
|
@ -16,7 +16,7 @@ interface NezhaDataResponse {
|
|||||||
|
|
||||||
export const GET = auth(async function GET(req) {
|
export const GET = auth(async function GET(req) {
|
||||||
if (!req.auth && getEnv("SitePassword")) {
|
if (!req.auth && getEnv("SitePassword")) {
|
||||||
redirect("/api/auth/signin");
|
redirect("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
const { searchParams } = new URL(req.url);
|
const { searchParams } = new URL(req.url);
|
||||||
|
@ -16,7 +16,7 @@ interface NezhaDataResponse {
|
|||||||
|
|
||||||
export const GET = auth(async function GET(req) {
|
export const GET = auth(async function GET(req) {
|
||||||
if (!req.auth && getEnv("SitePassword")) {
|
if (!req.auth && getEnv("SitePassword")) {
|
||||||
redirect("/api/auth/signin");
|
redirect("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
const { searchParams } = new URL(req.url);
|
const { searchParams } = new URL(req.url);
|
||||||
|
@ -16,7 +16,7 @@ interface NezhaDataResponse {
|
|||||||
|
|
||||||
export const GET = auth(async function GET(req) {
|
export const GET = auth(async function GET(req) {
|
||||||
if (!req.auth && getEnv("SitePassword")) {
|
if (!req.auth && getEnv("SitePassword")) {
|
||||||
redirect("/api/auth/signin");
|
redirect("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = (await GetNezhaData()) as NezhaDataResponse;
|
const response = (await GetNezhaData()) as NezhaDataResponse;
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import getEnv from "@/lib/env-entry";
|
import getEnv from "@/lib/env-entry";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
import getUnicodeFlagIcon from "country-flag-icons/unicode";
|
import getUnicodeFlagIcon from "country-flag-icons/unicode";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
export default function ServerFlag({ country_code }: { country_code: string }) {
|
export default function ServerFlag({
|
||||||
|
country_code,
|
||||||
|
className,
|
||||||
|
}: {
|
||||||
|
country_code: string;
|
||||||
|
className?: string;
|
||||||
|
}) {
|
||||||
const [supportsEmojiFlags, setSupportsEmojiFlags] = useState(false);
|
const [supportsEmojiFlags, setSupportsEmojiFlags] = useState(false);
|
||||||
|
|
||||||
const useSvgFlag = getEnv("NEXT_PUBLIC_ForceUseSvgFlag") === "true";
|
const useSvgFlag = getEnv("NEXT_PUBLIC_ForceUseSvgFlag") === "true";
|
||||||
@ -38,9 +45,9 @@ export default function ServerFlag({ country_code }: { country_code: string }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className="text-[12px] text-muted-foreground">
|
<span className={cn("text-[12px] text-muted-foreground", className)}>
|
||||||
{useSvgFlag || !supportsEmojiFlags ? (
|
{useSvgFlag || !supportsEmojiFlags ? (
|
||||||
<span className={`fi fi-${country_code}`}></span>
|
<span className={`fi fi-${country_code}`} />
|
||||||
) : (
|
) : (
|
||||||
getUnicodeFlagIcon(country_code)
|
getUnicodeFlagIcon(country_code)
|
||||||
)}
|
)}
|
||||||
|
@ -36,12 +36,10 @@ export function SignIn() {
|
|||||||
});
|
});
|
||||||
if (res?.error) {
|
if (res?.error) {
|
||||||
console.log("login error");
|
console.log("login error");
|
||||||
console.log(res);
|
|
||||||
setErrorState(true);
|
setErrorState(true);
|
||||||
setSuccessState(false);
|
setSuccessState(false);
|
||||||
} else {
|
} else {
|
||||||
console.log("login success");
|
console.log("login success");
|
||||||
console.log(res);
|
|
||||||
setErrorState(false);
|
setErrorState(false);
|
||||||
setSuccessState(true);
|
setSuccessState(true);
|
||||||
router.push("/");
|
router.push("/");
|
||||||
@ -75,7 +73,7 @@ export function SignIn() {
|
|||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<button
|
<button
|
||||||
className=" px-1.5 py-0.5 w-fit flex items-center gap-1 text-sm font-semibold rounded-[8px] border bg-card hover:brightness-95 transition-all text-card-foreground shadow-lg shadow-neutral-200/40 dark:shadow-none"
|
className="px-1.5 py-0.5 w-fit flex items-center gap-1 text-sm font-semibold rounded-[8px] border bg-card hover:brightness-95 transition-all text-card-foreground shadow-lg shadow-neutral-200/40 dark:shadow-none"
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
>
|
>
|
||||||
{t("Submit")}
|
{t("Submit")}
|
||||||
|
@ -14,7 +14,7 @@ export default function TabSwitch({
|
|||||||
setCurrentTab: (tab: string) => void;
|
setCurrentTab: (tab: string) => void;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="z-50 flex flex-col items-start overflow-x-scroll rounded-[50px]">
|
<div className="z-50 flex flex-col items-start 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
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
"Arch": "Arch",
|
"Arch": "Arch",
|
||||||
"Mem": "Mem",
|
"Mem": "Mem",
|
||||||
"Disk": "Disk",
|
"Disk": "Disk",
|
||||||
|
"Region": "Region",
|
||||||
"System": "System",
|
"System": "System",
|
||||||
"CPU": "CPU"
|
"CPU": "CPU"
|
||||||
},
|
},
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
"Arch": "アーキテクチャ",
|
"Arch": "アーキテクチャ",
|
||||||
"Mem": "メモリ",
|
"Mem": "メモリ",
|
||||||
"Disk": "ディスク",
|
"Disk": "ディスク",
|
||||||
|
"Region": "地域",
|
||||||
"System": "システム",
|
"System": "システム",
|
||||||
"CPU": "CPU"
|
"CPU": "CPU"
|
||||||
},
|
},
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
"Arch": "架構",
|
"Arch": "架構",
|
||||||
"Mem": "記憶體",
|
"Mem": "記憶體",
|
||||||
"Disk": "磁碟",
|
"Disk": "磁碟",
|
||||||
|
"Region": "地區",
|
||||||
"System": "系統",
|
"System": "系統",
|
||||||
"CPU": "CPU"
|
"CPU": "CPU"
|
||||||
},
|
},
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
"Arch": "架构",
|
"Arch": "架构",
|
||||||
"Mem": "内存",
|
"Mem": "内存",
|
||||||
"Disk": "磁盘",
|
"Disk": "磁盘",
|
||||||
|
"Region": "地区",
|
||||||
"System": "系统",
|
"System": "系统",
|
||||||
"CPU": "CPU"
|
"CPU": "CPU"
|
||||||
},
|
},
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev -p 3020",
|
"dev": "next dev -p 3020 --turbo",
|
||||||
"start": "node .next/standalone/server.js",
|
"start": "node .next/standalone/server.js",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
"build": "next build && cp -r .next/static .next/standalone/.next/ && cp -r public .next/standalone/",
|
"build": "next build && cp -r .next/static .next/standalone/.next/ && cp -r public .next/standalone/",
|
||||||
|
1638
styles/flag-icons.min.css
vendored
Normal file
1638
styles/flag-icons.min.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user