@@ -0,0 +1,377 @@
"use client"
import { useState } from "react"
import { ChevronLeft , Copy , Check , Info } from "lucide-react"
import { Button } from "@/components/ui/button"
import { useRouter } from "next/navigation"
import { useToast } from "@/components/ui/use-toast"
import { Tabs , TabsContent , TabsList , TabsTrigger } from "@/components/ui/tabs"
import { Card , CardContent , CardDescription , CardHeader , CardTitle } from "@/components/ui/card"
import { getApiGuideForScenario } from "@/docs/api-guide"
import { Badge } from "@/components/ui/badge"
import { Accordion , AccordionContent , AccordionItem , AccordionTrigger } from "@/components/ui/accordion"
export default function ApiDocPage ( { params } : { params : { channel : string ; id : string } } ) {
const router = useRouter ( )
const { toast } = useToast ( )
const [ copiedExample , setCopiedExample ] = useState < string | null > ( null )
const apiGuide = getApiGuideForScenario ( params . id , params . channel )
const copyToClipboard = ( text : string , exampleId : string ) = > {
navigator . clipboard . writeText ( text )
setCopiedExample ( exampleId )
toast ( {
title : "已复制代码" ,
description : "代码示例已复制到剪贴板" ,
} )
setTimeout ( ( ) = > {
setCopiedExample ( null )
} , 2000 )
}
return (
< div className = "min-h-screen bg-gray-50/30" >
< header className = "sticky top-0 z-10 bg-white border-b border-gray-200 shadow-sm" >
< div className = "flex items-center justify-between h-16 px-6" >
< div className = "flex items-center space-x-4" >
< Button variant = "ghost" size = "icon" onClick = { ( ) = > router . back ( ) } >
< ChevronLeft className = "h-5 w-5" / >
< / Button >
< div >
< h1 className = "text-xl font-semibold text-gray-900" > { apiGuide . title } < / h1 >
< p className = "text-sm text-gray-500 mt-1" > API接口文档 < / p >
< / div >
< / div >
< div className = "flex items-center gap-3" >
< Button
variant = "outline"
size = "sm"
onClick = { ( ) = > window . open ( ` ${ window . location . origin } /scenarios/ ${ params . channel } ` , "_self" ) }
>
返 回 计 划 列 表
< / Button >
< / div >
< / div >
< / header >
< div className = "container mx-auto py-8 px-6 max-w-5xl" >
{ /* API密钥卡片 */ }
< Card className = "mb-8" >
< CardHeader >
< div className = "flex items-center space-x-3" >
< div className = "w-10 h-10 bg-blue-100 rounded-lg flex items-center justify-center" >
< Info className = "h-5 w-5 text-blue-600" / >
< / div >
< div >
< CardTitle className = "text-lg" > API密钥 < / CardTitle >
< CardDescription > 用 于 身 份 验 证 , 请 妥 善 保 管 , 不 要 在 客 户 端 代 码 中 暴 露 它 < / CardDescription >
< / div >
< / div >
< / CardHeader >
< CardContent >
< div className = "space-y-6" >
< div className = "bg-gray-50 rounded-lg p-4 border" >
< div className = "flex items-center justify-between" >
< code className = "text-sm font-mono text-gray-800" > api_1_xqbint74 < / code >
< Button variant = "outline" size = "sm" onClick = { ( ) = > copyToClipboard ( "api_1_xqbint74" , "api-key" ) } >
{ copiedExample === "api-key" ? < Check className = "h-4 w-4" / > : < Copy className = "h-4 w-4" / > }
< / Button >
< / div >
< / div >
< div className = "bg-amber-50 border border-amber-200 rounded-lg p-4" >
< div className = "flex items-start space-x-3" >
< Info className = "h-5 w-5 text-amber-600 mt-0.5 flex-shrink-0" / >
< div >
< p className = "text-sm font-medium text-amber-800 mb-1" > 安 全 提 示 < / p >
< p className = "text-sm text-amber-700" >
请 妥 善 保 管 您 的 API密钥 , 不 要 在 客 户 端 代 码 中 暴 露 它 。 建 议 在 服 务 器 端 使 用 该 接 口 。
< / p >
< / div >
< / div >
< / div >
< / div >
< / CardContent >
< / Card >
{ /* 接口地址卡片 */ }
< Card className = "mb-8" >
< CardHeader >
< CardTitle className = "text-lg" > 接 口 地 址 < / CardTitle >
< CardDescription > 使 用 此 接 口 直 接 导 入 客 户 资 料 到 该 获 客 计 划 , 支 持 多 种 编 程 语 言 < / CardDescription >
< / CardHeader >
< CardContent >
< div className = "space-y-4" >
< div className = "bg-gray-50 rounded-lg p-4 border" >
< div className = "flex items-center justify-between mb-3" >
< span className = "text-sm font-medium text-gray-700" > POST 请 求 地 址 < / span >
< Button
variant = "outline"
size = "sm"
onClick = { ( ) = >
copyToClipboard (
"https://kzminfd0rplrm7owmj4b.lite.vusercontent.net/api/scenarios/post" ,
"api-url" ,
)
}
>
{ copiedExample === "api-url" ? < Check className = "h-4 w-4" / > : < Copy className = "h-4 w-4" / > }
< / Button >
< / div >
< code className = "text-xs font-mono text-gray-800 break-all" >
https : //kzminfd0rplrm7owmj4b.lite.vusercontent.net/api/scenarios/post
< / code >
< / div >
< div className = "grid md:grid-cols-2 gap-4" >
< div className = "space-y-2" >
< h4 className = "text-sm font-medium text-gray-900" > 必 要 参 数 < / h4 >
< div className = "space-y-1" >
< Badge variant = "outline" className = "text-blue-600 border-blue-200" >
name ( 姓 名 )
< / Badge >
< Badge variant = "outline" className = "text-blue-600 border-blue-200" >
phone ( 电 话 )
< / Badge >
< / div >
< / div >
< div className = "space-y-2" >
< h4 className = "text-sm font-medium text-gray-900" > 可 选 参 数 < / h4 >
< div className = "space-y-1" >
< Badge variant = "outline" className = "text-gray-600 border-gray-200" >
source ( 来 源 )
< / Badge >
< Badge variant = "outline" className = "text-gray-600 border-gray-200" >
remark ( 备 注 )
< / Badge >
< Badge variant = "outline" className = "text-gray-600 border-gray-200" >
tags ( 标 签 )
< / Badge >
< / div >
< / div >
< / div >
< / div >
< / CardContent >
< / Card >
{ /* 接口文档卡片 */ }
< Card className = "mb-8" >
< CardHeader >
< CardTitle className = "text-lg" > 接 口 文 档 < / CardTitle >
< CardDescription > 详 细 的 API规范和集成指南 < / CardDescription >
< / CardHeader >
< CardContent >
< div className = "flex flex-col sm:flex-row gap-4" >
< Button variant = "outline" className = "flex-1 h-12 bg-transparent" >
< div className = "text-center" >
< div className = "font-medium" > 查 看 代 码 示 例 < / div >
< div className = "text-xs text-gray-500" > 多 种 语 言 示 例 < / div >
< / div >
< / Button >
< Button variant = "outline" className = "flex-1 h-12 bg-transparent" >
< div className = "text-center" >
< div className = "font-medium" > 查 看 集 成 指 南 < / div >
< div className = "text-xs text-gray-500" > 详 细 集 成 步 骤 < / div >
< / div >
< / Button >
< / div >
< / CardContent >
< / Card >
{ /* 快速测试卡片 */ }
< Card >
< CardHeader >
< CardTitle className = "text-lg" > 快 速 测 试 < / CardTitle >
< CardDescription > 使 用 以 下 URL可以快速测试接口是否正常工作 < / CardDescription >
< / CardHeader >
< CardContent >
< div className = "bg-gray-50 rounded-lg p-4 border" >
< div className = "flex items-center justify-between mb-3" >
< span className = "text-sm font-medium text-gray-700" > 测 试 URL < / span >
< Button
variant = "outline"
size = "sm"
onClick = { ( ) = >
copyToClipboard (
"https://kzminfd0rplrm7owmj4b.lite.vusercontent.net/api/scenarios/poster/1/webhook?name=测试客户&phone=13800138000" ,
"test-url" ,
)
}
>
{ copiedExample === "test-url" ? < Check className = "h-4 w-4" / > : < Copy className = "h-4 w-4" / > }
< / Button >
< / div >
< code className = "text-xs font-mono text-gray-800 break-all" >
https : //kzminfd0rplrm7owmj4b.lite.vusercontent.net/api/scenarios/poster/1/webhook?name=测试客户&phone=13800138000
< / code >
< / div >
< div className = "mt-4 p-3 bg-green-50 border border-green-200 rounded-lg" >
< p className = "text-sm text-green-700" > 💡 点 击 上 方 链 接 或 复 制 到 浏 览 器 中 访 问 , 即 可 快 速 测 试 接 口 连 通 性 < / p >
< / div >
< / CardContent >
< / Card >
{ /* 详细文档手风琴 */ }
< div className = "mt-8" >
< Accordion type = "single" collapsible className = "space-y-4" >
{ apiGuide . endpoints . map ( ( endpoint , index ) = > (
< AccordionItem key = { index } value = { ` endpoint- ${ index } ` } className = "border rounded-lg" >
< AccordionTrigger className = "px-6 py-4 hover:bg-gray-50" >
< div className = "flex items-center space-x-3" >
< Badge className = "bg-green-100 text-green-800 border-green-200" > { endpoint . method } < / Badge >
< span className = "font-mono text-sm text-gray-700" > { endpoint . url } < / span >
< / div >
< / AccordionTrigger >
< AccordionContent className = "px-6 pb-6" >
< div className = "space-y-6" >
< p className = "text-sm text-gray-700" > { endpoint . description } < / p >
< div >
< h4 className = "text-sm font-medium mb-3 text-gray-900" > 请 求 头 < / h4 >
< div className = "bg-gray-50 rounded-lg p-4 space-y-3" >
{ endpoint . headers . map ( ( header , i ) = > (
< div key = { i } className = "flex items-start space-x-3" >
< Badge variant = "outline" className = "font-mono text-xs" >
{ header . required ? "*" : "" }
{ header . name }
< / Badge >
< div className = "flex-1" >
< p className = "text-sm font-medium" > { header . value } < / p >
< p className = "text-xs text-gray-500 mt-1" > { header . description } < / p >
< / div >
< / div >
) ) }
< / div >
< / div >
< div >
< h4 className = "text-sm font-medium mb-3 text-gray-900" > 请 求 参 数 < / h4 >
< div className = "bg-gray-50 rounded-lg p-4 space-y-3" >
{ endpoint . parameters . map ( ( param , i ) = > (
< div key = { i } className = "flex items-start space-x-3" >
< Badge variant = "outline" className = "font-mono text-xs" >
{ param . required ? "*" : "" }
{ param . name }
< / Badge >
< div className = "flex-1" >
< p className = "text-sm" >
< span className = "text-gray-500 font-mono text-xs" > { param . type } < / span >
< / p >
< p className = "text-xs text-gray-500 mt-1" > { param . description } < / p >
< / div >
< / div >
) ) }
< / div >
< / div >
< div >
< h4 className = "text-sm font-medium mb-3 text-gray-900" > 响 应 示 例 < / h4 >
< pre className = "bg-gray-50 rounded-lg p-4 text-xs overflow-auto border" >
{ JSON . stringify ( endpoint . response , null , 2 ) }
< / pre >
< / div >
< / div >
< / AccordionContent >
< / AccordionItem >
) ) }
< / Accordion >
< / div >
{ /* 代码示例 */ }
< Card className = "mt-8" id = "examples" >
< CardHeader >
< CardTitle className = "text-lg" > 代 码 示 例 < / CardTitle >
< CardDescription > 以 下 是 不 同 编 程 语 言 的 接 口 调 用 示 例 < / CardDescription >
< / CardHeader >
< CardContent >
< Tabs defaultValue = { apiGuide . examples [ 0 ] . language } >
< TabsList className = "mb-6" >
{ apiGuide . examples . map ( ( example ) = > (
< TabsTrigger key = { example . language } value = { example . language } >
{ example . title }
< / TabsTrigger >
) ) }
< / TabsList >
{ apiGuide . examples . map ( ( example ) = > (
< TabsContent key = { example . language } value = { example . language } >
< div className = "relative" >
< pre className = "bg-gray-50 p-6 rounded-lg overflow-auto text-sm border" > { example . code } < / pre >
< Button
variant = "outline"
size = "sm"
className = "absolute top-3 right-3 bg-transparent"
onClick = { ( ) = > copyToClipboard ( example . code , example . language ) }
>
{ copiedExample === example . language ? (
< Check className = "h-4 w-4" / >
) : (
< Copy className = "h-4 w-4" / >
) }
< / Button >
< / div >
< / TabsContent >
) ) }
< / Tabs >
< / CardContent >
< / Card >
{ /* 集成指南 */ }
< div className = "mt-8 space-y-6" id = "integration" >
< h3 className = "text-xl font-semibold text-gray-900" > 集 成 指 南 < / h3 >
< Card >
< CardHeader >
< CardTitle className = "text-base" > 集 简 云 平 台 集 成 < / CardTitle >
< / CardHeader >
< CardContent >
< ol className = "list-decimal list-inside space-y-3 text-sm" >
< li > 登 录 集 简 云 平 台 < / li >
< li > 导 航 至 "应用集成" & gt ; "外部接口" < / li >
< li > 选 择 "添加新接口" , 输 入 存 客 宝 接 口 信 息 < / li >
< li > 配 置 回 调 参 数 , 将 "X-API-KEY" 设 置 为 您 的 API密钥 < / li >
< li >
设 置 接 口 URL为 :
< code className = "bg-gray-100 px-2 py-1 rounded ml-2 text-xs" > { apiGuide . endpoints [ 0 ] . url } < / code >
< / li >
< li > 映 射 必 要 字 段 ( name , phone等 ) < / li >
< li > 保 存 并 启 用 集 成 < / li >
< / ol >
< / CardContent >
< / Card >
< Card >
< CardHeader >
< CardTitle className = "text-base" > 问 题 排 查 < / CardTitle >
< / CardHeader >
< CardContent className = "space-y-4" >
< div >
< h4 className = "text-sm font-medium mb-2 text-gray-900" > 接 口 认 证 失 败 < / h4 >
< p className = "text-sm text-gray-700" >
请 确 保 X - API - KEY正确无误 , 此 密 钥 区 分 大 小 写 。 如 需 重 置 密 钥 , 请 联 系 管 理 员 。
< / p >
< / div >
< div >
< h4 className = "text-sm font-medium mb-2 text-gray-900" > 数 据 格 式 错 误 < / h4 >
< p className = "text-sm text-gray-700" >
确 保 所 有 必 填 字 段 已 提 供 , 并 且 字 段 类 型 正 确 。 特 别 是 电 话 号 码 格 式 需 符 合 标 准 。
< / p >
< / div >
< div >
< h4 className = "text-sm font-medium mb-2 text-gray-900" > 请 求 频 率 限 制 < / h4 >
< p className = "text-sm text-gray-700" >
单 个 API密钥每分钟最多可发送30个请求 , 超 过 限 制 将 被 暂 时 限 制 。 对 于 大 批 量 数 据 , 请 使 用 批 量 接 口 。
< / p >
< / div >
< / CardContent >
< / Card >
< / div >
< / div >
< / div >
)
}