feat(users): integrate user info and services APIs into 3-tab detail panel with proper padding
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
import { ApiReferenceReact } from '@scalar/api-reference-react'
|
||||
import '@scalar/api-reference-react/style.css'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import { useState } from 'react'
|
||||
import { ApiError } from '@/api/client'
|
||||
import { fetchApiDocument, type ApiDocument } from '@/api/modules/api-docs'
|
||||
import { PERM, requirePermission } from '@/auth/permissions'
|
||||
import { PageHeader } from '@/components/page-header'
|
||||
import { Button } from '@/components/ui/button'
|
||||
|
||||
export const Route = createFileRoute('/_authed/api-docs')({
|
||||
beforeLoad: () => requirePermission(PERM.API_DOCS_READ),
|
||||
component: ApiDocumentationPage,
|
||||
})
|
||||
|
||||
const DOCUMENTS: Array<{ value: ApiDocument; label: string }> = [
|
||||
{ value: 'public', label: '公共 API' },
|
||||
{ value: 'admin', label: '管理端 API' },
|
||||
]
|
||||
|
||||
function ApiDocumentationPage() {
|
||||
const [document, setDocument] = useState<ApiDocument>('public')
|
||||
const specification = useQuery({
|
||||
queryKey: ['api-docs', document],
|
||||
queryFn: ({ signal }) => fetchApiDocument(document, signal),
|
||||
})
|
||||
|
||||
const notGenerated =
|
||||
specification.error instanceof ApiError &&
|
||||
specification.error.code === 'API_DOCUMENT_NOT_GENERATED'
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageHeader
|
||||
title="API 文档"
|
||||
description="仅向拥有开发者文档权限的后台账号开放"
|
||||
actions={
|
||||
<div className="flex gap-2">
|
||||
{DOCUMENTS.map((item) => (
|
||||
<Button
|
||||
key={item.value}
|
||||
variant={document === item.value ? 'default' : 'outline'}
|
||||
onClick={() => setDocument(item.value)}
|
||||
>
|
||||
{item.label}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
|
||||
{specification.isPending && (
|
||||
<div className="rounded-lg border p-8 text-center text-sm text-muted-foreground">
|
||||
正在加载 API 文档…
|
||||
</div>
|
||||
)}
|
||||
|
||||
{notGenerated && (
|
||||
<div className="rounded-lg border border-dashed p-8 text-center">
|
||||
<p className="font-medium">文档尚未生成</p>
|
||||
<p className="mt-2 text-sm text-muted-foreground">
|
||||
请联系运维人员运行 <code className="font-mono">php artisan api-docs:generate</code>。
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{specification.isError && !notGenerated && (
|
||||
<div className="rounded-lg border border-destructive/40 p-8 text-center">
|
||||
<p className="font-medium text-destructive">API 文档加载失败</p>
|
||||
<Button className="mt-4" variant="outline" onClick={() => void specification.refetch()}>
|
||||
重试
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{specification.data && (
|
||||
<div className="overflow-hidden rounded-lg border">
|
||||
<ApiReferenceReact
|
||||
key={document}
|
||||
configuration={{
|
||||
content: specification.data,
|
||||
agent: { disabled: true },
|
||||
hideModels: false,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user