sync: soul-admin 页面 | 原因: 前端页面修改
This commit is contained in:
@@ -1,14 +1,20 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { Card, CardContent } from '@/components/ui/card'
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
|
||||
import { RefreshCw } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { RefreshCw, Send } from 'lucide-react'
|
||||
import { Pagination } from '@/components/ui/Pagination'
|
||||
import { get } from '@/api/client'
|
||||
import { get, post } from '@/api/client'
|
||||
|
||||
interface MatchRecord {
|
||||
id: string; userId: string; matchedUserId: string; matchType: string
|
||||
phone?: string; wechatId?: string; userNickname?: string; matchedNickname?: string
|
||||
createdAt: string
|
||||
createdAt: string; ckbStatus?: string
|
||||
}
|
||||
|
||||
const typeLabels: Record<string, string> = {
|
||||
investor: '资源对接', mentor: '导师顾问', team: '团队招募',
|
||||
}
|
||||
|
||||
export function ResourceDockingTab() {
|
||||
@@ -17,32 +23,62 @@ export function ResourceDockingTab() {
|
||||
const [page, setPage] = useState(1)
|
||||
const [pageSize, setPageSize] = useState(10)
|
||||
const [isLoading, setIsLoading] = useState(true)
|
||||
const [typeFilter, setTypeFilter] = useState('investor')
|
||||
const [pushingId, setPushingId] = useState<string | null>(null)
|
||||
|
||||
async function load() {
|
||||
setIsLoading(true)
|
||||
try {
|
||||
const params = new URLSearchParams({ page: String(page), pageSize: String(pageSize), matchType: 'investor' })
|
||||
const params = new URLSearchParams({ page: String(page), pageSize: String(pageSize), matchType: typeFilter })
|
||||
const data = await get<{ success?: boolean; records?: MatchRecord[]; total?: number }>(`/api/db/match-records?${params}`)
|
||||
if (data?.success) { setRecords(data.records || []); setTotal(data.total ?? 0) }
|
||||
} catch (e) { console.error(e) }
|
||||
finally { setIsLoading(false) }
|
||||
}
|
||||
|
||||
useEffect(() => { load() }, [page])
|
||||
useEffect(() => { load() }, [page, typeFilter])
|
||||
|
||||
const pushToCKB = async (record: MatchRecord) => {
|
||||
if (!record.phone && !record.wechatId) {
|
||||
alert('该记录无联系方式,无法推送到存客宝')
|
||||
return
|
||||
}
|
||||
setPushingId(record.id)
|
||||
try {
|
||||
const res = await post<{ success?: boolean; message?: string }>('/api/ckb/join', {
|
||||
type: record.matchType || 'investor',
|
||||
phone: record.phone || '',
|
||||
wechat: record.wechatId || '',
|
||||
userId: record.userId,
|
||||
name: record.userNickname || '',
|
||||
})
|
||||
alert(res?.message || (res?.success ? '推送成功' : '推送失败'))
|
||||
} catch (e) {
|
||||
alert('推送失败: ' + (e instanceof Error ? e.message : '网络错误'))
|
||||
} finally {
|
||||
setPushingId(null)
|
||||
}
|
||||
}
|
||||
|
||||
const totalPages = Math.ceil(total / pageSize) || 1
|
||||
const hasContact = (r: MatchRecord) => !!(r.phone || r.wechatId)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<div>
|
||||
<p className="text-gray-400">资源对接匹配记录,共 {total} 条</p>
|
||||
<p className="text-gray-500 text-xs mt-1">用户填写「我能帮到你什么」和「我需要什么帮助」后提交到存客宝</p>
|
||||
<p className="text-gray-400">点击获客:有人填写手机号/微信号的直接显示,可一键推送到存客宝</p>
|
||||
<p className="text-gray-500 text-xs mt-1">共 {total} 条记录 — 有联系方式的可触发存客宝添加好友</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<select value={typeFilter} onChange={e => { setTypeFilter(e.target.value); setPage(1) }}
|
||||
className="bg-[#0f2137] border border-gray-700 text-white rounded-lg px-3 py-2 text-sm">
|
||||
{Object.entries(typeLabels).map(([k, v]) => <option key={k} value={k}>{v}</option>)}
|
||||
</select>
|
||||
<Button onClick={load} disabled={isLoading} variant="outline" className="border-gray-600 text-gray-300 hover:bg-gray-700/50 bg-transparent">
|
||||
<RefreshCw className={`w-4 h-4 mr-2 ${isLoading ? 'animate-spin' : ''}`} /> 刷新
|
||||
</Button>
|
||||
</div>
|
||||
<button type="button" onClick={load} disabled={isLoading}
|
||||
className="flex items-center gap-2 px-4 py-2 rounded-lg border border-gray-600 text-gray-300 hover:bg-gray-700/50 transition-colors disabled:opacity-50">
|
||||
<RefreshCw className={`w-4 h-4 ${isLoading ? 'animate-spin' : ''}`} /> 刷新
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<Card className="bg-[#0f2137] border-gray-700/50 shadow-xl">
|
||||
@@ -56,24 +92,40 @@ export function ResourceDockingTab() {
|
||||
<TableRow className="bg-[#0a1628] hover:bg-[#0a1628] border-gray-700">
|
||||
<TableHead className="text-gray-400">发起人</TableHead>
|
||||
<TableHead className="text-gray-400">匹配到</TableHead>
|
||||
<TableHead className="text-gray-400">类型</TableHead>
|
||||
<TableHead className="text-gray-400">联系方式</TableHead>
|
||||
<TableHead className="text-gray-400">时间</TableHead>
|
||||
<TableHead className="text-gray-400 text-right">操作</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{records.map(r => (
|
||||
<TableRow key={r.id} className="hover:bg-[#0a1628] border-gray-700/50">
|
||||
<TableCell className="text-white">{r.userNickname || r.userId}</TableCell>
|
||||
<TableCell className="text-white">{r.matchedNickname || r.matchedUserId}</TableCell>
|
||||
<TableCell className="text-gray-400 text-sm">
|
||||
{r.phone && <div>📱 {r.phone}</div>}
|
||||
{r.wechatId && <div>💬 {r.wechatId}</div>}
|
||||
{!r.phone && !r.wechatId && '-'}
|
||||
<TableRow key={r.id} className={`border-gray-700/50 ${hasContact(r) ? 'hover:bg-[#0a1628]' : 'opacity-60'}`}>
|
||||
<TableCell className="text-white">{r.userNickname || r.userId?.slice(0, 12)}</TableCell>
|
||||
<TableCell className="text-white">{r.matchedNickname || r.matchedUserId?.slice(0, 12)}</TableCell>
|
||||
<TableCell>
|
||||
<Badge className="bg-[#38bdac]/20 text-[#38bdac] border-0">{typeLabels[r.matchType] || r.matchType}</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="text-sm">
|
||||
{r.phone && <div className="text-green-400">📱 {r.phone}</div>}
|
||||
{r.wechatId && <div className="text-blue-400">💬 {r.wechatId}</div>}
|
||||
{!r.phone && !r.wechatId && <span className="text-gray-600">无联系方式</span>}
|
||||
</TableCell>
|
||||
<TableCell className="text-gray-400 text-sm">{r.createdAt ? new Date(r.createdAt).toLocaleString() : '-'}</TableCell>
|
||||
<TableCell className="text-right">
|
||||
{hasContact(r) ? (
|
||||
<Button size="sm" onClick={() => pushToCKB(r)} disabled={pushingId === r.id}
|
||||
className="bg-[#38bdac] hover:bg-[#2da396] text-white text-xs h-7 px-3">
|
||||
<Send className="w-3 h-3 mr-1" />
|
||||
{pushingId === r.id ? '推送中...' : '推送CKB'}
|
||||
</Button>
|
||||
) : (
|
||||
<span className="text-gray-600 text-xs">—</span>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell className="text-gray-400">{r.createdAt ? new Date(r.createdAt).toLocaleString() : '-'}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
{records.length === 0 && <TableRow><TableCell colSpan={4} className="text-center py-12 text-gray-500">暂无资源对接记录</TableCell></TableRow>}
|
||||
{records.length === 0 && <TableRow><TableCell colSpan={6} className="text-center py-12 text-gray-500">暂无记录</TableCell></TableRow>}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<Pagination page={page} totalPages={totalPages} total={total} pageSize={pageSize} onPageChange={setPage} onPageSizeChange={n => { setPageSize(n); setPage(1) }} />
|
||||
|
||||
Reference in New Issue
Block a user