Files
users/components/dialogs/api-doc-dialog.tsx

223 lines
8.3 KiB
TypeScript
Raw Normal View History

"use client"
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { ScrollArea } from "@/components/ui/scroll-area"
import { Code, Copy, ExternalLink } from "lucide-react"
interface APIDocDialogProps {
open: boolean
onOpenChange: (open: boolean) => void
api?: {
name: string
endpoint: string
method: string
description: string
}
}
export function APIDocDialog({ open, onOpenChange, api }: APIDocDialogProps) {
const copyToClipboard = (text: string) => {
navigator.clipboard.writeText(text)
}
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-3xl max-h-[80vh]">
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
<Code className="w-5 h-5" />
API文档 - {api?.name || "API服务"}
</DialogTitle>
<DialogDescription>{api?.description}</DialogDescription>
</DialogHeader>
<div className="flex items-center gap-2 p-3 bg-slate-50 rounded-lg">
<Badge className={api?.method === "GET" ? "bg-blue-100 text-blue-700" : "bg-green-100 text-green-700"}>
{api?.method || "GET"}
</Badge>
<code className="flex-1 text-sm">{api?.endpoint || "/api/v1/example"}</code>
<Button variant="ghost" size="sm" onClick={() => copyToClipboard(api?.endpoint || "")}>
<Copy className="w-4 h-4" />
</Button>
</div>
<Tabs defaultValue="request">
<TabsList className="grid w-full grid-cols-4">
<TabsTrigger value="request"></TabsTrigger>
<TabsTrigger value="response"></TabsTrigger>
<TabsTrigger value="example"></TabsTrigger>
<TabsTrigger value="errors"></TabsTrigger>
</TabsList>
<TabsContent value="request" className="mt-4">
<ScrollArea className="h-[300px]">
<table className="w-full text-sm">
<thead>
<tr className="border-b">
<th className="text-left py-2 px-3"></th>
<th className="text-left py-2 px-3"></th>
<th className="text-left py-2 px-3"></th>
<th className="text-left py-2 px-3"></th>
</tr>
</thead>
<tbody>
<tr className="border-b">
<td className="py-2 px-3">
<code>user_id</code>
</td>
<td className="py-2 px-3">string</td>
<td className="py-2 px-3">
<Badge className="bg-red-100 text-red-700"></Badge>
</td>
<td className="py-2 px-3"></td>
</tr>
<tr className="border-b">
<td className="py-2 px-3">
<code>fields</code>
</td>
<td className="py-2 px-3">array</td>
<td className="py-2 px-3">
<Badge variant="outline"></Badge>
</td>
<td className="py-2 px-3"></td>
</tr>
<tr className="border-b">
<td className="py-2 px-3">
<code>include_tags</code>
</td>
<td className="py-2 px-3">boolean</td>
<td className="py-2 px-3">
<Badge variant="outline"></Badge>
</td>
<td className="py-2 px-3">, true</td>
</tr>
</tbody>
</table>
</ScrollArea>
</TabsContent>
<TabsContent value="response" className="mt-4">
<ScrollArea className="h-[300px]">
<pre className="p-4 bg-slate-900 rounded-lg text-sm text-green-400 overflow-x-auto">
{`{
"code": 0,
"message": "success",
"data": {
"user_id": "u_123456",
"name": "张三",
"phone": "138****5678",
"email": "zhang***@example.com",
"tags": ["高价值", "活跃用户", "VIP"],
"portrait": {
"age_group": "25-35",
"gender": "male",
"city": "上海",
"consumption_level": "high"
},
"value_score": {
"rfm_score": 85,
"ltv": 12580,
"churn_risk": 0.12
}
}
}`}
</pre>
</ScrollArea>
</TabsContent>
<TabsContent value="example" className="mt-4">
<ScrollArea className="h-[300px]">
<div className="space-y-4">
<div>
<h4 className="text-sm font-medium mb-2">cURL</h4>
<pre className="p-4 bg-slate-900 rounded-lg text-sm text-green-400 overflow-x-auto">
{`curl -X GET "https://api.shenshoushou.com/api/v1/user/portrait?user_id=u_123456" \\
-H "Authorization: Bearer YOUR_API_KEY" \\
-H "Content-Type: application/json"`}
</pre>
</div>
<div>
<h4 className="text-sm font-medium mb-2">JavaScript</h4>
<pre className="p-4 bg-slate-900 rounded-lg text-sm text-green-400 overflow-x-auto">
{`const response = await fetch(
"https://api.shenshoushou.com/api/v1/user/portrait?user_id=u_123456",
{
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}
}
);
const data = await response.json();`}
</pre>
</div>
</div>
</ScrollArea>
</TabsContent>
<TabsContent value="errors" className="mt-4">
<ScrollArea className="h-[300px]">
<table className="w-full text-sm">
<thead>
<tr className="border-b">
<th className="text-left py-2 px-3"></th>
<th className="text-left py-2 px-3"></th>
<th className="text-left py-2 px-3"></th>
</tr>
</thead>
<tbody>
<tr className="border-b">
<td className="py-2 px-3">
<code>400</code>
</td>
<td className="py-2 px-3"></td>
<td className="py-2 px-3"></td>
</tr>
<tr className="border-b">
<td className="py-2 px-3">
<code>401</code>
</td>
<td className="py-2 px-3"></td>
<td className="py-2 px-3">API Key是否正确</td>
</tr>
<tr className="border-b">
<td className="py-2 px-3">
<code>404</code>
</td>
<td className="py-2 px-3"></td>
<td className="py-2 px-3">ID是否正确</td>
</tr>
<tr className="border-b">
<td className="py-2 px-3">
<code>429</code>
</td>
<td className="py-2 px-3"></td>
<td className="py-2 px-3"></td>
</tr>
<tr className="border-b">
<td className="py-2 px-3">
<code>500</code>
</td>
<td className="py-2 px-3"></td>
<td className="py-2 px-3"></td>
</tr>
</tbody>
</table>
</ScrollArea>
</TabsContent>
</Tabs>
<div className="flex justify-end gap-2">
<Button variant="outline">
<ExternalLink className="w-4 h-4 mr-2" />
线
</Button>
</div>
</DialogContent>
</Dialog>
)
}