mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-01 14:46:36 +08:00
135 lines
4.3 KiB
TypeScript
135 lines
4.3 KiB
TypeScript
'use client';
|
|
|
|
import Link from 'next/link';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { marked } from 'marked';
|
|
|
|
import { EmptyState } from '@/components/feedback/empty-state';
|
|
import { ErrorState } from '@/components/feedback/error-state';
|
|
import { LoadingState } from '@/components/feedback/loading-state';
|
|
import { AppCard } from '@/components/ui/app-card';
|
|
import { StatusBadge } from '@/components/ui/status-badge';
|
|
import { getPublicStatus } from '@/features/auth/api/public';
|
|
import { getAboutContent } from '@/features/settings/api/settings';
|
|
import { formatDateTime } from '@/lib/utils/date';
|
|
|
|
function getErrorMessage(error: unknown) {
|
|
return error instanceof Error ? error.message : '请求失败,请稍后重试。';
|
|
}
|
|
|
|
export function AboutPage() {
|
|
const aboutQuery = useQuery({
|
|
queryKey: ['about'],
|
|
queryFn: getAboutContent,
|
|
});
|
|
|
|
const statusQuery = useQuery({
|
|
queryKey: ['public-status'],
|
|
queryFn: getPublicStatus,
|
|
});
|
|
|
|
if (aboutQuery.isLoading || statusQuery.isLoading) {
|
|
return <LoadingState />;
|
|
}
|
|
|
|
if (aboutQuery.isError) {
|
|
return (
|
|
<ErrorState
|
|
title="关于页加载失败"
|
|
description={getErrorMessage(aboutQuery.error)}
|
|
/>
|
|
);
|
|
}
|
|
|
|
if (statusQuery.isError) {
|
|
return (
|
|
<ErrorState
|
|
title="系统状态加载失败"
|
|
description={getErrorMessage(statusQuery.error)}
|
|
/>
|
|
);
|
|
}
|
|
|
|
const aboutContent = aboutQuery.data?.trim() ?? '';
|
|
const status = statusQuery.data;
|
|
|
|
if (!status) {
|
|
return (
|
|
<EmptyState
|
|
title="暂无系统信息"
|
|
description="未能获取 OpenFlare 的公开状态信息。"
|
|
/>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<AppCard
|
|
title="关于 OpenFlare"
|
|
description="公开展示当前系统简介、版本信息与项目入口。"
|
|
action={<StatusBadge label={status.version || 'dev'} variant="info" />}
|
|
>
|
|
<div className="grid gap-4 md:grid-cols-3">
|
|
<div className="rounded-2xl border border-[var(--border-default)] bg-[var(--surface-muted)] px-4 py-4">
|
|
<p className="text-xs tracking-[0.2em] text-[var(--foreground-muted)] uppercase">
|
|
系统名称
|
|
</p>
|
|
<p className="mt-2 text-sm font-medium text-[var(--foreground-primary)]">
|
|
{status.system_name || 'OpenFlare'}
|
|
</p>
|
|
</div>
|
|
<div className="rounded-2xl border border-[var(--border-default)] bg-[var(--surface-muted)] px-4 py-4">
|
|
<p className="text-xs tracking-[0.2em] text-[var(--foreground-muted)] uppercase">
|
|
Server 启动时间
|
|
</p>
|
|
<p className="mt-2 text-sm font-medium text-[var(--foreground-primary)]">
|
|
{formatDateTime(new Date(status.start_time * 1000))}
|
|
</p>
|
|
</div>
|
|
<div className="rounded-2xl border border-[var(--border-default)] bg-[var(--surface-muted)] px-4 py-4">
|
|
<p className="text-xs tracking-[0.2em] text-[var(--foreground-muted)] uppercase">
|
|
项目仓库
|
|
</p>
|
|
<a
|
|
href="https://github.com/Rain-kl/OpenFlare"
|
|
target="_blank"
|
|
rel="noreferrer"
|
|
className="mt-2 block text-sm font-medium text-[var(--brand-primary)] transition hover:opacity-80"
|
|
>
|
|
github.com/Rain-kl/OpenFlare
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</AppCard>
|
|
|
|
{aboutContent ? (
|
|
<AppCard
|
|
title="项目介绍"
|
|
description="以下内容由系统设置中的“关于内容”维护。"
|
|
>
|
|
<div
|
|
className="prose prose-sm max-w-none text-[var(--foreground-primary)] [&_a]:text-[var(--brand-primary)]"
|
|
dangerouslySetInnerHTML={{
|
|
__html: marked.parse(aboutContent) as string,
|
|
}}
|
|
/>
|
|
</AppCard>
|
|
) : (
|
|
<EmptyState
|
|
title="尚未配置关于内容"
|
|
description="可在设置页的“其他设置”标签中编写 Markdown / HTML 内容,这里会自动同步展示。"
|
|
/>
|
|
)}
|
|
|
|
<div className="flex flex-wrap gap-3 text-sm">
|
|
<Link
|
|
href="/login"
|
|
className="text-[var(--brand-primary)] transition hover:opacity-80"
|
|
>
|
|
前往登录
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|