414 lines
11 KiB
TypeScript
414 lines
11 KiB
TypeScript
|
|
import type { ReactNode } from "react"
|
|||
|
|
|
|||
|
|
interface ApiGuide {
|
|||
|
|
title: string
|
|||
|
|
description: string
|
|||
|
|
endpoint: string
|
|||
|
|
method: "GET" | "POST" | "PUT" | "DELETE"
|
|||
|
|
parameters: {
|
|||
|
|
name: string
|
|||
|
|
type: string
|
|||
|
|
required: boolean
|
|||
|
|
description: string
|
|||
|
|
}[]
|
|||
|
|
requestExample: string
|
|||
|
|
responseExample: string
|
|||
|
|
notes?: string
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
interface ScenarioApiGuides {
|
|||
|
|
[key: string]: ApiGuide[]
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// API指南数据
|
|||
|
|
const apiGuides: ScenarioApiGuides = {
|
|||
|
|
phone: [
|
|||
|
|
{
|
|||
|
|
title: "获取电话获客列表",
|
|||
|
|
description: "获取所有电话获客场景的列表",
|
|||
|
|
endpoint: "/api/scenarios/phone",
|
|||
|
|
method: "GET",
|
|||
|
|
parameters: [
|
|||
|
|
{
|
|||
|
|
name: "page",
|
|||
|
|
type: "number",
|
|||
|
|
required: false,
|
|||
|
|
description: "页码,默认为1",
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: "limit",
|
|||
|
|
type: "number",
|
|||
|
|
required: false,
|
|||
|
|
description: "每页数量,默认为10",
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: "status",
|
|||
|
|
type: "string",
|
|||
|
|
required: false,
|
|||
|
|
description: "状态筛选,可选值:active, inactive",
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
requestExample: `
|
|||
|
|
GET /api/scenarios/phone?page=1&limit=10&status=active
|
|||
|
|
`,
|
|||
|
|
responseExample: `
|
|||
|
|
{
|
|||
|
|
"success": true,
|
|||
|
|
"data": {
|
|||
|
|
"total": 25,
|
|||
|
|
"page": 1,
|
|||
|
|
"limit": 10,
|
|||
|
|
"items": [
|
|||
|
|
{
|
|||
|
|
"id": "phone-1",
|
|||
|
|
"name": "电话获客计划1",
|
|||
|
|
"status": "active",
|
|||
|
|
"createdAt": "2023-05-20T10:30:00Z",
|
|||
|
|
"deviceCount": 3,
|
|||
|
|
"acquisitionCount": 120
|
|||
|
|
},
|
|||
|
|
// ...更多数据
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
`,
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
title: "创建电话获客场景",
|
|||
|
|
description: "创建新的电话获客场景",
|
|||
|
|
endpoint: "/api/scenarios/phone",
|
|||
|
|
method: "POST",
|
|||
|
|
parameters: [
|
|||
|
|
{
|
|||
|
|
name: "name",
|
|||
|
|
type: "string",
|
|||
|
|
required: true,
|
|||
|
|
description: "场景名称",
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: "devices",
|
|||
|
|
type: "array",
|
|||
|
|
required: true,
|
|||
|
|
description: "设备ID数组",
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: "tags",
|
|||
|
|
type: "array",
|
|||
|
|
required: false,
|
|||
|
|
description: "标签数组",
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: "settings",
|
|||
|
|
type: "object",
|
|||
|
|
required: false,
|
|||
|
|
description: "场景设置",
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
requestExample: `
|
|||
|
|
POST /api/scenarios/phone
|
|||
|
|
Content-Type: application/json
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
"name": "新电话获客计划",
|
|||
|
|
"devices": ["device-1", "device-2"],
|
|||
|
|
"tags": ["高意向", "新客户"],
|
|||
|
|
"settings": {
|
|||
|
|
"autoAdd": true,
|
|||
|
|
"speechToText": true,
|
|||
|
|
"callType": "both"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
`,
|
|||
|
|
responseExample: `
|
|||
|
|
{
|
|||
|
|
"success": true,
|
|||
|
|
"data": {
|
|||
|
|
"id": "phone-26",
|
|||
|
|
"name": "新电话获客计划",
|
|||
|
|
"status": "active",
|
|||
|
|
"createdAt": "2023-06-01T08:15:00Z"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
`,
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
haibao: [
|
|||
|
|
{
|
|||
|
|
title: "获取海报获客列表",
|
|||
|
|
description: "获取所有海报获客场景的列表",
|
|||
|
|
endpoint: "/api/scenarios/haibao",
|
|||
|
|
method: "GET",
|
|||
|
|
parameters: [
|
|||
|
|
{
|
|||
|
|
name: "page",
|
|||
|
|
type: "number",
|
|||
|
|
required: false,
|
|||
|
|
description: "页码,默认为1",
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: "limit",
|
|||
|
|
type: "number",
|
|||
|
|
required: false,
|
|||
|
|
description: "每页数量,默认为10",
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
requestExample: `
|
|||
|
|
GET /api/scenarios/haibao?page=1&limit=10
|
|||
|
|
`,
|
|||
|
|
responseExample: `
|
|||
|
|
{
|
|||
|
|
"success": true,
|
|||
|
|
"data": {
|
|||
|
|
"total": 15,
|
|||
|
|
"page": 1,
|
|||
|
|
"limit": 10,
|
|||
|
|
"items": [
|
|||
|
|
{
|
|||
|
|
"id": "haibao-1",
|
|||
|
|
"name": "618促销海报",
|
|||
|
|
"status": "active",
|
|||
|
|
"createdAt": "2023-05-15T09:20:00Z",
|
|||
|
|
"posterUrl": "https://example.com/posters/618.jpg",
|
|||
|
|
"scanCount": 230,
|
|||
|
|
"conversionCount": 45
|
|||
|
|
},
|
|||
|
|
// ...更多数据
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
`,
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
api: [
|
|||
|
|
{
|
|||
|
|
title: "API获客回调接口",
|
|||
|
|
description: "接收第三方系统推送的获客数据",
|
|||
|
|
endpoint: "/api/scenarios/api/callback",
|
|||
|
|
method: "POST",
|
|||
|
|
parameters: [
|
|||
|
|
{
|
|||
|
|
name: "token",
|
|||
|
|
type: "string",
|
|||
|
|
required: true,
|
|||
|
|
description: "API认证令牌",
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: "data",
|
|||
|
|
type: "array",
|
|||
|
|
required: true,
|
|||
|
|
description: "获客数据数组",
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
requestExample: `
|
|||
|
|
POST /api/scenarios/api/callback
|
|||
|
|
Content-Type: application/json
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
"token": "your_api_token",
|
|||
|
|
"data": [
|
|||
|
|
{
|
|||
|
|
"phone": "13800138000",
|
|||
|
|
"name": "张三",
|
|||
|
|
"source": "官网表单",
|
|||
|
|
"tags": ["高意向", "产品A"],
|
|||
|
|
"remark": "对产品A很感兴趣"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"phone": "13900139000",
|
|||
|
|
"name": "李四",
|
|||
|
|
"source": "线下活动",
|
|||
|
|
"tags": ["中意向"],
|
|||
|
|
"remark": "参加了6月15日的产品发布会"
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
`,
|
|||
|
|
responseExample: `
|
|||
|
|
{
|
|||
|
|
"success": true,
|
|||
|
|
"message": "数据接收成功",
|
|||
|
|
"data": {
|
|||
|
|
"received": 2,
|
|||
|
|
"processed": 2,
|
|||
|
|
"failed": 0
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
`,
|
|||
|
|
notes: "API令牌可在API获客场景详情页获取,请妥善保管",
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
title: "获取API获客统计数据",
|
|||
|
|
description: "获取API获客场景的统计数据",
|
|||
|
|
endpoint: "/api/scenarios/api/{id}/stats",
|
|||
|
|
method: "GET",
|
|||
|
|
parameters: [
|
|||
|
|
{
|
|||
|
|
name: "id",
|
|||
|
|
type: "string",
|
|||
|
|
required: true,
|
|||
|
|
description: "API获客场景ID",
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: "startDate",
|
|||
|
|
type: "string",
|
|||
|
|
required: false,
|
|||
|
|
description: "开始日期,格式:YYYY-MM-DD",
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
name: "endDate",
|
|||
|
|
type: "string",
|
|||
|
|
required: false,
|
|||
|
|
description: "结束日期,格式:YYYY-MM-DD",
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
requestExample: `
|
|||
|
|
GET /api/scenarios/api/api-1/stats?startDate=2023-05-01&endDate=2023-05-31
|
|||
|
|
`,
|
|||
|
|
responseExample: `
|
|||
|
|
{
|
|||
|
|
"success": true,
|
|||
|
|
"data": {
|
|||
|
|
"total": 156,
|
|||
|
|
"daily": [
|
|||
|
|
{
|
|||
|
|
"date": "2023-05-01",
|
|||
|
|
"count": 12
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"date": "2023-05-02",
|
|||
|
|
"count": 8
|
|||
|
|
},
|
|||
|
|
// ...更多数据
|
|||
|
|
],
|
|||
|
|
"sources": [
|
|||
|
|
{
|
|||
|
|
"name": "官网表单",
|
|||
|
|
"count": 78
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "线下活动",
|
|||
|
|
"count": 45
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "合作伙伴",
|
|||
|
|
"count": 33
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
`,
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取特定场景的API指南
|
|||
|
|
export function getApiGuideForScenario(scenarioType: string): ApiGuide[] {
|
|||
|
|
return apiGuides[scenarioType] || []
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 渲染API指南组件
|
|||
|
|
export function ApiGuideComponent({
|
|||
|
|
scenarioType,
|
|||
|
|
children,
|
|||
|
|
}: {
|
|||
|
|
scenarioType: string
|
|||
|
|
children?: ReactNode
|
|||
|
|
}): JSX.Element {
|
|||
|
|
const guides = getApiGuideForScenario(scenarioType)
|
|||
|
|
|
|||
|
|
if (guides.length === 0) {
|
|||
|
|
return (
|
|||
|
|
<div className="p-6 bg-gray-50 rounded-lg">
|
|||
|
|
<h3 className="text-lg font-medium">暂无API文档</h3>
|
|||
|
|
<p className="text-gray-500 mt-2">该场景类型暂未提供API接口文档</p>
|
|||
|
|
{children}
|
|||
|
|
</div>
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div className="space-y-8">
|
|||
|
|
{guides.map((guide, index) => (
|
|||
|
|
<div key={index} className="border rounded-lg overflow-hidden">
|
|||
|
|
<div className="bg-gray-50 p-4 border-b">
|
|||
|
|
<h3 className="text-lg font-medium">{guide.title}</h3>
|
|||
|
|
<p className="text-gray-500 mt-1">{guide.description}</p>
|
|||
|
|
</div>
|
|||
|
|
<div className="p-4 space-y-4">
|
|||
|
|
<div>
|
|||
|
|
<h4 className="font-medium text-sm text-gray-500">接口地址</h4>
|
|||
|
|
<div className="flex items-center mt-1">
|
|||
|
|
<span className="px-2 py-1 bg-blue-100 text-blue-800 rounded text-sm font-mono">{guide.method}</span>
|
|||
|
|
<span className="ml-2 font-mono">{guide.endpoint}</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div>
|
|||
|
|
<h4 className="font-medium text-sm text-gray-500">参数说明</h4>
|
|||
|
|
<div className="mt-1 border rounded-lg overflow-hidden">
|
|||
|
|
<table className="min-w-full divide-y divide-gray-200">
|
|||
|
|
<thead className="bg-gray-50">
|
|||
|
|
<tr>
|
|||
|
|
<th className="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|||
|
|
参数名
|
|||
|
|
</th>
|
|||
|
|
<th className="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|||
|
|
类型
|
|||
|
|
</th>
|
|||
|
|
<th className="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|||
|
|
必填
|
|||
|
|
</th>
|
|||
|
|
<th className="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|||
|
|
说明
|
|||
|
|
</th>
|
|||
|
|
</tr>
|
|||
|
|
</thead>
|
|||
|
|
<tbody className="bg-white divide-y divide-gray-200">
|
|||
|
|
{guide.parameters.map((param, paramIndex) => (
|
|||
|
|
<tr key={paramIndex}>
|
|||
|
|
<td className="px-4 py-2 text-sm font-mono">{param.name}</td>
|
|||
|
|
<td className="px-4 py-2 text-sm">{param.type}</td>
|
|||
|
|
<td className="px-4 py-2 text-sm">
|
|||
|
|
{param.required ? (
|
|||
|
|
<span className="text-red-500">是</span>
|
|||
|
|
) : (
|
|||
|
|
<span className="text-gray-500">否</span>
|
|||
|
|
)}
|
|||
|
|
</td>
|
|||
|
|
<td className="px-4 py-2 text-sm">{param.description}</td>
|
|||
|
|
</tr>
|
|||
|
|
))}
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|||
|
|
<div>
|
|||
|
|
<h4 className="font-medium text-sm text-gray-500">请求示例</h4>
|
|||
|
|
<pre className="mt-1 p-3 bg-gray-800 text-gray-100 rounded-lg overflow-auto text-xs font-mono">
|
|||
|
|
{guide.requestExample}
|
|||
|
|
</pre>
|
|||
|
|
</div>
|
|||
|
|
<div>
|
|||
|
|
<h4 className="font-medium text-sm text-gray-500">响应示例</h4>
|
|||
|
|
<pre className="mt-1 p-3 bg-gray-800 text-gray-100 rounded-lg overflow-auto text-xs font-mono">
|
|||
|
|
{guide.responseExample}
|
|||
|
|
</pre>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{guide.notes && (
|
|||
|
|
<div className="bg-yellow-50 border border-yellow-100 rounded-lg p-3">
|
|||
|
|
<h4 className="font-medium text-sm text-yellow-800">注意事项</h4>
|
|||
|
|
<p className="mt-1 text-sm text-yellow-700">{guide.notes}</p>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
))}
|
|||
|
|
{children}
|
|||
|
|
</div>
|
|||
|
|
)
|
|||
|
|
}
|