sync: soul-admin 页面 | 原因: 前端页面修改
This commit is contained in:
129
soul-admin/src/pages/find-partner/tabs/CKBConfigPanel.tsx
Normal file
129
soul-admin/src/pages/find-partner/tabs/CKBConfigPanel.tsx
Normal file
@@ -0,0 +1,129 @@
|
||||
import { useState } from 'react'
|
||||
import { Card, CardContent } from '@/components/ui/card'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import {
|
||||
RefreshCw, Zap, CheckCircle2, XCircle, Smartphone, FileText, ExternalLink,
|
||||
} from 'lucide-react'
|
||||
import { get, post } from '@/api/client'
|
||||
|
||||
interface TestResult {
|
||||
endpoint: string; label: string
|
||||
method: 'GET' | 'POST'; status: 'idle' | 'testing' | 'success' | 'error'
|
||||
message?: string; responseTime?: number
|
||||
}
|
||||
|
||||
const typeMap = ['partner', 'investor', 'mentor', 'team']
|
||||
|
||||
export function CKBConfigPanel() {
|
||||
const [testPhone, setTestPhone] = useState('13800000000')
|
||||
const [testWechat, setTestWechat] = useState('')
|
||||
const [tests, setTests] = useState<TestResult[]>([
|
||||
{ endpoint: '/api/ckb/join', label: '找伙伴', method: 'POST', status: 'idle' },
|
||||
{ endpoint: '/api/ckb/join', label: '资源对接', method: 'POST', status: 'idle' },
|
||||
{ endpoint: '/api/ckb/join', label: '导师顾问', method: 'POST', status: 'idle' },
|
||||
{ endpoint: '/api/ckb/join', label: '团队招募', method: 'POST', status: 'idle' },
|
||||
{ endpoint: '/api/ckb/match', label: '匹配上报', method: 'POST', status: 'idle' },
|
||||
{ endpoint: '/api/miniprogram/ckb/lead', label: '链接卡若', method: 'POST', status: 'idle' },
|
||||
{ endpoint: '/api/match/config', label: '匹配配置', method: 'GET', status: 'idle' },
|
||||
])
|
||||
|
||||
const getBody = (idx: number) => {
|
||||
const phone = testPhone.trim(); const wechat = testWechat.trim()
|
||||
if (idx <= 3) return { type: typeMap[idx], phone: phone || undefined, wechat: wechat || undefined, userId: 'admin_test', name: '后台测试' }
|
||||
if (idx === 4) return { matchType: 'partner', phone: phone || undefined, wechat: wechat || undefined, userId: 'admin_test', nickname: '后台测试', matchedUser: { id: 'test', nickname: '测试', matchScore: 88 } }
|
||||
if (idx === 5) return { phone: phone || undefined, wechatId: wechat || undefined, userId: 'admin_test', name: '后台测试' }
|
||||
return {}
|
||||
}
|
||||
|
||||
const testOne = async (idx: number) => {
|
||||
const t = tests[idx]
|
||||
if (t.method === 'POST' && !testPhone.trim() && !testWechat.trim()) { alert('请填写测试手机号'); return }
|
||||
const next = [...tests]; next[idx] = { ...t, status: 'testing', message: undefined, responseTime: undefined }; setTests(next)
|
||||
const start = performance.now()
|
||||
try {
|
||||
const res = t.method === 'GET'
|
||||
? await get<{ success?: boolean; message?: string }>(t.endpoint)
|
||||
: await post<{ success?: boolean; message?: string }>(t.endpoint, getBody(idx))
|
||||
const elapsed = Math.round(performance.now() - start)
|
||||
const msg = res?.message || ''
|
||||
const ok = res?.success === true || msg.includes('已存在') || msg.includes('已加入') || msg.includes('已提交')
|
||||
const n = [...tests]; n[idx] = { ...t, status: ok ? 'success' : 'error', message: msg || (ok ? '正常' : '异常'), responseTime: elapsed }; setTests(n)
|
||||
} catch (e: unknown) {
|
||||
const elapsed = Math.round(performance.now() - start)
|
||||
const n = [...tests]; n[idx] = { ...t, status: 'error', message: e instanceof Error ? e.message : '失败', responseTime: elapsed }; setTests(n)
|
||||
}
|
||||
}
|
||||
|
||||
const testAll = async () => {
|
||||
if (!testPhone.trim() && !testWechat.trim()) { alert('请填写测试手机号'); return }
|
||||
for (let i = 0; i < tests.length; i++) await testOne(i)
|
||||
}
|
||||
|
||||
return (
|
||||
<Card className="bg-[#0f2137] border-orange-500/30 mb-6">
|
||||
<CardContent className="p-5">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<h3 className="text-white font-semibold">存客宝配置与接口测试</h3>
|
||||
<Badge className="bg-orange-500/20 text-orange-400 border-0 text-xs">CKB</Badge>
|
||||
<a href="https://ckbapi.quwanzhi.com" target="_blank" rel="noreferrer"
|
||||
className="text-orange-400/60 text-xs hover:text-orange-400 flex items-center gap-1">
|
||||
<ExternalLink className="w-3 h-3" /> API 文档
|
||||
</a>
|
||||
</div>
|
||||
<Button onClick={testAll} size="sm" className="bg-orange-500 hover:bg-orange-600 text-white">
|
||||
<Zap className="w-3.5 h-3.5 mr-1" /> 全部测试
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-3 mb-4">
|
||||
<div className="flex items-center gap-2 flex-1">
|
||||
<Smartphone className="w-4 h-4 text-gray-500 shrink-0" />
|
||||
<div className="flex-1">
|
||||
<Label className="text-gray-500 text-xs">测试手机号</Label>
|
||||
<Input className="bg-[#0a1628] border-gray-700 text-white h-8 text-sm mt-0.5" value={testPhone} onChange={e => setTestPhone(e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 flex-1">
|
||||
<span className="text-gray-500 text-sm shrink-0">💬</span>
|
||||
<div className="flex-1">
|
||||
<Label className="text-gray-500 text-xs">微信号(可选)</Label>
|
||||
<Input className="bg-[#0a1628] border-gray-700 text-white h-8 text-sm mt-0.5" value={testWechat} onChange={e => setTestWechat(e.target.value)} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-2">
|
||||
{tests.map((t, idx) => (
|
||||
<div key={`${t.endpoint}-${idx}`} className="flex items-center justify-between bg-[#0a1628] rounded-lg px-3 py-2 border border-gray-700/30">
|
||||
<div className="flex items-center gap-2 min-w-0">
|
||||
{t.status === 'idle' && <div className="w-2 h-2 rounded-full bg-gray-600 shrink-0" />}
|
||||
{t.status === 'testing' && <RefreshCw className="w-3 h-3 text-yellow-400 animate-spin shrink-0" />}
|
||||
{t.status === 'success' && <CheckCircle2 className="w-3 h-3 text-green-400 shrink-0" />}
|
||||
{t.status === 'error' && <XCircle className="w-3 h-3 text-red-400 shrink-0" />}
|
||||
<span className="text-white text-xs truncate">{t.label}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 shrink-0">
|
||||
{t.responseTime !== undefined && <span className="text-gray-600 text-[10px]">{t.responseTime}ms</span>}
|
||||
<button type="button" onClick={() => testOne(idx)} disabled={t.status === 'testing'}
|
||||
className="text-orange-400/60 hover:text-orange-400 text-[10px] disabled:opacity-50">测试</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex gap-3 mt-3 text-xs">
|
||||
<a href="https://ckbapi.quwanzhi.com/v1/api/scenarios" target="_blank" rel="noreferrer"
|
||||
className="text-gray-500 hover:text-orange-400 flex items-center gap-1">
|
||||
<FileText className="w-3 h-3" /> 场景获客API
|
||||
</a>
|
||||
<span className="text-gray-700">|</span>
|
||||
<span className="text-gray-600">Key: fyngh-ec...</span>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user