mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-04 15:06:37 +08:00
系统控制台完成更新
This commit is contained in:
@@ -1,10 +1,25 @@
|
||||
"use client"
|
||||
|
||||
import {Info, Server} from "lucide-react"
|
||||
import packageJson from "../../../package.json"
|
||||
import {APP_VERSION, APP_BUILD_DATE} from "@/lib/app-info"
|
||||
import {apiConfig} from "@/lib/services"
|
||||
import {useMutation, useQuery} from "@tanstack/react-query"
|
||||
import {ExternalLink, RefreshCw, Server, Sparkles} from "lucide-react"
|
||||
import {toast} from "sonner"
|
||||
|
||||
import {AdminService, apiConfig} from "@/lib/services"
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger
|
||||
} from "@/components/ui/alert-dialog"
|
||||
import {Badge} from "@/components/ui/badge"
|
||||
import {Button} from "@/components/ui/button"
|
||||
import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/components/ui/card"
|
||||
import {Spinner} from "@/components/ui/spinner"
|
||||
|
||||
function InfoRow({ label, value }: { label: string; value: React.ReactNode }) {
|
||||
return (
|
||||
@@ -21,26 +36,131 @@ interface InfoTabProps {
|
||||
}
|
||||
|
||||
export function InfoTab({ systemConfigsLength, authSourcesLength }: InfoTabProps) {
|
||||
const updateQuery = useQuery({
|
||||
queryKey: ["admin", "update"],
|
||||
queryFn: () => AdminService.getUpdateStatus(),
|
||||
refetchInterval: 30 * 60 * 1000,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
})
|
||||
|
||||
const applyUpdateMutation = useMutation({
|
||||
mutationFn: () => AdminService.applyUpdate(),
|
||||
onSuccess: () => {
|
||||
toast.success("升级包已校验完成,服务正在重启")
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
toast.error(error.message || "应用升级失败")
|
||||
},
|
||||
})
|
||||
|
||||
const update = updateQuery.data
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
|
||||
<Card className="border border-dashed shadow-sm">
|
||||
<CardHeader className="border-b border-dashed pb-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-1.5 rounded-lg bg-muted text-muted-foreground">
|
||||
<Info className="size-4" />
|
||||
</div>
|
||||
<div>
|
||||
<CardTitle className="text-base font-semibold">应用信息</CardTitle>
|
||||
<CardDescription className="text-xs">当前前端应用的版本与构建信息</CardDescription>
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="rounded-lg bg-muted p-1.5 text-muted-foreground">
|
||||
<Sparkles className="size-4" />
|
||||
</div>
|
||||
<div>
|
||||
<CardTitle className="text-base font-semibold">应用更新</CardTitle>
|
||||
<CardDescription className="text-xs">
|
||||
检查上游 GitHub Actions Release 并升级当前服务
|
||||
</CardDescription>
|
||||
</div>
|
||||
</div>
|
||||
{update?.update_available ? (
|
||||
<Badge>发现新版本</Badge>
|
||||
) : update ? (
|
||||
<Badge variant="secondary">已是最新</Badge>
|
||||
) : null}
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-4">
|
||||
<InfoRow label="应用名称" value={packageJson.name} />
|
||||
<InfoRow label="版本号" value={APP_VERSION} />
|
||||
{APP_BUILD_DATE && <InfoRow label="构建时间" value={APP_BUILD_DATE} />}
|
||||
<InfoRow label="Next.js" value={(packageJson as { dependencies?: Record<string, string> }).dependencies?.next} />
|
||||
<InfoRow label="React" value={(packageJson as { dependencies?: Record<string, string> }).dependencies?.react} />
|
||||
<CardContent className="flex flex-col gap-4 pt-4">
|
||||
{updateQuery.isLoading ? (
|
||||
<div className="flex min-h-32 items-center justify-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : updateQuery.isError ? (
|
||||
<div className="flex min-h-32 flex-col items-center justify-center gap-3 text-center">
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{updateQuery.error.message || "无法获取上游版本信息"}
|
||||
</p>
|
||||
<Button type="button" variant="outline" size="sm" onClick={() => updateQuery.refetch()}>
|
||||
<RefreshCw data-icon="inline-start" />
|
||||
重新检查
|
||||
</Button>
|
||||
</div>
|
||||
) : update ? (
|
||||
<>
|
||||
<div>
|
||||
<InfoRow label="当前版本" value={update.current_version} />
|
||||
<InfoRow label="最新版本" value={update.latest_version} />
|
||||
{update.build_time && <InfoRow label="构建时间" value={update.build_time} />}
|
||||
<InfoRow label="运行平台" value={update.platform} />
|
||||
<InfoRow label="上游仓库" value={update.upstream_repository} />
|
||||
<InfoRow label="Release 资产" value={update.asset_name} />
|
||||
</div>
|
||||
|
||||
{update.release_notes && (
|
||||
<div className="flex flex-col gap-2 rounded-md border border-dashed p-3">
|
||||
<p className="text-xs font-medium">更新说明</p>
|
||||
<p className="max-h-40 overflow-y-auto whitespace-pre-wrap text-xs leading-relaxed text-muted-foreground">
|
||||
{update.release_notes}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-wrap justify-end gap-2">
|
||||
<Button type="button" variant="ghost" size="sm" onClick={() => updateQuery.refetch()} disabled={updateQuery.isFetching}>
|
||||
{updateQuery.isFetching ? <Spinner data-icon="inline-start" /> : <RefreshCw data-icon="inline-start" />}
|
||||
检查更新
|
||||
</Button>
|
||||
{update.release_url && (
|
||||
<Button asChild variant="outline" size="sm">
|
||||
<a href={update.release_url} target="_blank" rel="noreferrer">
|
||||
<ExternalLink data-icon="inline-start" />
|
||||
查看 Release
|
||||
</a>
|
||||
</Button>
|
||||
)}
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button type="button" size="sm" disabled={!update.can_upgrade || applyUpdateMutation.isPending}>
|
||||
{applyUpdateMutation.isPending && <Spinner data-icon="inline-start" />}
|
||||
立即升级
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>升级到 {update.latest_version}?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
服务将下载并校验 {update.asset_name},随后替换当前二进制并重启。请确保安装目录可写,且服务允许原地重启。
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>取消</AlertDialogCancel>
|
||||
<AlertDialogAction onClick={() => applyUpdateMutation.mutate()}>
|
||||
确认升级
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</div>
|
||||
|
||||
{!update.can_upgrade && (
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{update.current_version === "dev"
|
||||
? "开发构建没有可比较的 Release 版本,不能执行自动升级。"
|
||||
: update.update_available
|
||||
? "当前平台暂不支持自动替换二进制,请从 Release 页面手动升级。"
|
||||
: "当前版本无需升级。"}
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
) : null}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user