sync: soul-admin 页面 | 原因: 前端页面修改
This commit is contained in:
@@ -5,7 +5,7 @@ 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,
|
||||
RefreshCw, Zap, CheckCircle2, XCircle, Smartphone, FileText, ExternalLink, Save,
|
||||
} from 'lucide-react'
|
||||
import { get, post } from '@/api/client'
|
||||
|
||||
@@ -20,6 +20,10 @@ const typeMap = ['partner', 'investor', 'mentor', 'team']
|
||||
export function CKBConfigPanel() {
|
||||
const [testPhone, setTestPhone] = useState('13800000000')
|
||||
const [testWechat, setTestWechat] = useState('')
|
||||
const [apiUrl, setApiUrl] = useState('https://ckbapi.quwanzhi.com/v1/api/scenarios')
|
||||
const [apiKey, setApiKey] = useState('fyngh-ecy9h-qkdae-epwd5-rz6kd')
|
||||
const [docNotes, setDocNotes] = useState('')
|
||||
const [isSaving, setIsSaving] = useState(false)
|
||||
const [tests, setTests] = useState<TestResult[]>([
|
||||
{ endpoint: '/api/ckb/join', label: '找伙伴', method: 'POST', status: 'idle' },
|
||||
{ endpoint: '/api/ckb/join', label: '资源对接', method: 'POST', status: 'idle' },
|
||||
@@ -62,6 +66,36 @@ export function CKBConfigPanel() {
|
||||
for (let i = 0; i < tests.length; i++) await testOne(i)
|
||||
}
|
||||
|
||||
async function loadConfig() {
|
||||
try {
|
||||
const data = await get<{ data?: { apiUrl?: string; apiKey?: string; docNotes?: string } }>('/api/db/config/full?key=ckb_config')
|
||||
const c = data?.data
|
||||
if (c?.apiUrl) setApiUrl(c.apiUrl)
|
||||
if (c?.apiKey) setApiKey(c.apiKey)
|
||||
if (c?.docNotes) setDocNotes(c.docNotes)
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
async function saveConfig() {
|
||||
setIsSaving(true)
|
||||
try {
|
||||
const res = await post<{ success?: boolean; error?: string }>('/api/db/config', {
|
||||
key: 'ckb_config',
|
||||
value: { apiUrl, apiKey, docNotes },
|
||||
description: '存客宝接口配置',
|
||||
})
|
||||
alert(res?.success !== false ? '存客宝配置已保存' : `保存失败: ${res?.error || '未知错误'}`)
|
||||
} catch (e) {
|
||||
alert(`保存失败: ${e instanceof Error ? e.message : '网络错误'}`)
|
||||
} finally {
|
||||
setIsSaving(false)
|
||||
}
|
||||
}
|
||||
|
||||
useState(() => { void loadConfig(); return null })
|
||||
|
||||
return (
|
||||
<Card className="bg-[#0f2137] border-orange-500/30 mb-6">
|
||||
<CardContent className="p-5">
|
||||
@@ -79,6 +113,22 @@ export function CKBConfigPanel() {
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 mb-5">
|
||||
<div className="space-y-1">
|
||||
<Label className="text-gray-500 text-xs">API 地址</Label>
|
||||
<Input className="bg-[#0a1628] border-gray-700 text-white h-9 text-sm" value={apiUrl} onChange={e => setApiUrl(e.target.value)} />
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label className="text-gray-500 text-xs">API Key</Label>
|
||||
<Input className="bg-[#0a1628] border-gray-700 text-white h-9 text-sm" value={apiKey} onChange={e => setApiKey(e.target.value)} />
|
||||
</div>
|
||||
<div className="flex items-end">
|
||||
<Button onClick={saveConfig} disabled={isSaving} className="bg-[#38bdac] hover:bg-[#2da396] text-white w-full">
|
||||
<Save className="w-4 h-4 mr-2" /> {isSaving ? '保存中...' : '保存配置'}
|
||||
</Button>
|
||||
</div>
|
||||
</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" />
|
||||
@@ -121,7 +171,30 @@ export function CKBConfigPanel() {
|
||||
<FileText className="w-3 h-3" /> 场景获客API
|
||||
</a>
|
||||
<span className="text-gray-700">|</span>
|
||||
<span className="text-gray-600">Key: fyngh-ec...</span>
|
||||
<span className="text-gray-600">Key: {apiKey ? `${apiKey.slice(0, 8)}...` : '未配置'}</span>
|
||||
</div>
|
||||
|
||||
<div className="mt-5 grid grid-cols-1 xl:grid-cols-2 gap-4">
|
||||
<div className="bg-[#0a1628] rounded-lg border border-gray-700/30 p-4">
|
||||
<h4 className="text-white text-sm font-medium mb-3">场景获客接口摘要</h4>
|
||||
<div className="space-y-2 text-xs text-gray-400">
|
||||
<p><span className="text-gray-300">接口:</span><code className="text-orange-300">POST /v1/api/scenarios</code></p>
|
||||
<p><span className="text-gray-300">必填鉴权:</span><code>apiKey</code>、<code>sign</code>、<code>timestamp</code></p>
|
||||
<p><span className="text-gray-300">至少一项:</span><code>phone</code> 或 <code>wechatId</code></p>
|
||||
<p><span className="text-gray-300">可选字段:</span><code>name</code>、<code>source</code>、<code>remark</code>、<code>tags</code>、<code>siteTags</code>、<code>portrait</code></p>
|
||||
<p><span className="text-gray-300">签名:</span>排除 <code>sign/apiKey/portrait</code>,按键升序拼接值后双重 MD5</p>
|
||||
<p><span className="text-gray-300">成功返回:</span><code>{"{ code: 200, message: '新增成功|已存在' }"}</code></p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-[#0a1628] rounded-lg border border-gray-700/30 p-4">
|
||||
<h4 className="text-white text-sm font-medium mb-3">说明备注(可编辑)</h4>
|
||||
<textarea
|
||||
className="w-full min-h-[140px] bg-[#0f2137] border border-gray-700 rounded-md text-sm text-gray-300 p-3 outline-none focus:border-orange-500/50 resize-y"
|
||||
value={docNotes}
|
||||
onChange={(e) => setDocNotes(e.target.value)}
|
||||
placeholder="这里可记录存客宝 Token、计划说明、接口对接约定、回复率统计规则等。"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
Reference in New Issue
Block a user