mirror of
https://github.com/woodchen-ink/nezha-dash-v1.git
synced 2025-07-18 09:31:55 +08:00
feat: error page
This commit is contained in:
parent
3633664345
commit
13915634c5
61
src/App.tsx
61
src/App.tsx
@ -3,6 +3,7 @@ import React, { useEffect, useState } from "react"
|
|||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { Route, BrowserRouter as Router, Routes } from "react-router-dom"
|
import { Route, BrowserRouter as Router, Routes } from "react-router-dom"
|
||||||
|
|
||||||
|
import ErrorBoundary from "./components/ErrorBoundary"
|
||||||
import Footer from "./components/Footer"
|
import Footer from "./components/Footer"
|
||||||
import Header from "./components/Header"
|
import Header from "./components/Header"
|
||||||
import { InjectContext } from "./lib/inject"
|
import { InjectContext } from "./lib/inject"
|
||||||
@ -56,37 +57,39 @@ const App: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Router basename={import.meta.env.BASE_URL}>
|
<Router basename={import.meta.env.BASE_URL}>
|
||||||
{/* 固定定位的背景层 */}
|
<ErrorBoundary>
|
||||||
{customBackgroundImage && (
|
{/* 固定定位的背景层 */}
|
||||||
|
{customBackgroundImage && (
|
||||||
|
<div
|
||||||
|
className={cn("fixed inset-0 z-0 bg-cover min-h-lvh bg-no-repeat bg-center", {
|
||||||
|
"hidden sm:block": customMobileBackgroundImage,
|
||||||
|
})}
|
||||||
|
style={{ backgroundImage: `url(${customBackgroundImage})` }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{customMobileBackgroundImage && (
|
||||||
|
<div
|
||||||
|
className={cn("fixed inset-0 z-0 bg-cover min-h-lvh bg-no-repeat bg-center sm:hidden")}
|
||||||
|
style={{ backgroundImage: `url(${customMobileBackgroundImage})` }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<div
|
<div
|
||||||
className={cn("fixed inset-0 z-0 bg-cover min-h-lvh bg-no-repeat bg-center", {
|
className={cn("flex min-h-screen w-full flex-col", {
|
||||||
"hidden sm:block": customMobileBackgroundImage,
|
"bg-background": !customBackgroundImage,
|
||||||
})}
|
})}
|
||||||
style={{ backgroundImage: `url(${customBackgroundImage})` }}
|
>
|
||||||
/>
|
<main className="flex z-20 min-h-[calc(100vh-calc(var(--spacing)*16))] flex-1 flex-col gap-4 p-4 md:p-10 md:pt-8">
|
||||||
)}
|
<Header />
|
||||||
{customMobileBackgroundImage && (
|
<Routes>
|
||||||
<div
|
<Route path="/" element={<Server />} />
|
||||||
className={cn("fixed inset-0 z-0 bg-cover min-h-lvh bg-no-repeat bg-center sm:hidden")}
|
<Route path="/server/:id" element={<ServerDetail />} />
|
||||||
style={{ backgroundImage: `url(${customMobileBackgroundImage})` }}
|
<Route path="/error" element={<ErrorPage />} />
|
||||||
/>
|
<Route path="*" element={<NotFound />} />
|
||||||
)}
|
</Routes>
|
||||||
<div
|
<Footer />
|
||||||
className={cn("flex min-h-screen w-full flex-col", {
|
</main>
|
||||||
"bg-background": !customBackgroundImage,
|
</div>
|
||||||
})}
|
</ErrorBoundary>
|
||||||
>
|
|
||||||
<main className="flex z-20 min-h-[calc(100vh-calc(var(--spacing)*16))] flex-1 flex-col gap-4 p-4 md:p-10 md:pt-8">
|
|
||||||
<Header />
|
|
||||||
<Routes>
|
|
||||||
<Route path="/" element={<Server />} />
|
|
||||||
<Route path="/server/:id" element={<ServerDetail />} />
|
|
||||||
<Route path="/error" element={<ErrorPage />} />
|
|
||||||
<Route path="*" element={<NotFound />} />
|
|
||||||
</Routes>
|
|
||||||
<Footer />
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</Router>
|
</Router>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
36
src/components/ErrorBoundary.tsx
Normal file
36
src/components/ErrorBoundary.tsx
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import React from "react"
|
||||||
|
|
||||||
|
import ErrorPage from "../pages/ErrorPage"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
hasError: boolean
|
||||||
|
error?: Error
|
||||||
|
}
|
||||||
|
|
||||||
|
class ErrorBoundary extends React.Component<Props, State> {
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props)
|
||||||
|
this.state = { hasError: false }
|
||||||
|
}
|
||||||
|
|
||||||
|
static getDerivedStateFromError(error: Error): State {
|
||||||
|
return {
|
||||||
|
hasError: true,
|
||||||
|
error,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.state.hasError) {
|
||||||
|
return <ErrorPage code={500} message={this.state.error?.message || "应用程序发生错误"} />
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.props.children
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ErrorBoundary
|
@ -1,6 +1,4 @@
|
|||||||
import { Button } from "@/components/ui/button"
|
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { useNavigate } from "react-router-dom"
|
|
||||||
|
|
||||||
interface ErrorPageProps {
|
interface ErrorPageProps {
|
||||||
code?: string | number
|
code?: string | number
|
||||||
@ -8,7 +6,6 @@ interface ErrorPageProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function ErrorPage({ code = "500", message }: ErrorPageProps) {
|
export default function ErrorPage({ code = "500", message }: ErrorPageProps) {
|
||||||
const navigate = useNavigate()
|
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -16,14 +13,6 @@ export default function ErrorPage({ code = "500", message }: ErrorPageProps) {
|
|||||||
<div className="flex flex-col items-center gap-2">
|
<div className="flex flex-col items-center gap-2">
|
||||||
<h1 className="text-4xl font-semibold">{code}</h1>
|
<h1 className="text-4xl font-semibold">{code}</h1>
|
||||||
<p className="text-xl text-muted-foreground">{message || t("error.somethingWentWrong")}</p>
|
<p className="text-xl text-muted-foreground">{message || t("error.somethingWentWrong")}</p>
|
||||||
<div className="flex gap-2">
|
|
||||||
<Button onClick={() => window.location.reload()} variant="outline">
|
|
||||||
{t("error.tryAgain")}
|
|
||||||
</Button>
|
|
||||||
<Button onClick={() => navigate("/")} className="mt-2">
|
|
||||||
{t("error.backToHome")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user