import { useState, useEffect, useCallback } from 'react' import { verificationsApi, type VerificationListItem, type VerificationDetail, type VerificationStatus } from '@/api' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Badge } from '@/components/ui/badge' import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' import { Textarea } from '@/components/ui/textarea' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select' import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog' import { PaginationNavigator } from '@/components/ui/pagination' import { Search, RefreshCw, Eye, CheckCircle, XCircle, Loader2 } from 'lucide-react' const statusColors: Record = { not_submitted: 'bg-gray-500', pending: 'bg-yellow-500', approved: 'bg-green-500', rejected: 'bg-red-500', } const statusText: Record = { not_submitted: '未提交', pending: '待审核', approved: '已通过', rejected: '已拒绝', } const identityText: Record = { student: '学生', teacher: '教师', staff: '职工', alumni: '校友', external: '外部人员', general: '普通用户', } export default function Verifications() { const [verifications, setVerifications] = useState([]) const [loading, setLoading] = useState(true) const [total, setTotal] = useState(0) const [page, setPage] = useState(1) const pageSize = 10 const [keyword, setKeyword] = useState('') const [statusFilter, setStatusFilter] = useState('all') const [detailOpen, setDetailOpen] = useState(false) const [selectedVerification, setSelectedVerification] = useState(null) const [detailLoading, setDetailLoading] = useState(false) const [reviewDialogOpen, setReviewDialogOpen] = useState(false) const [reviewLoading, setReviewLoading] = useState(false) const [rejectReason, setRejectReason] = useState('') const loadVerifications = useCallback(async () => { setLoading(true) try { const params = { page, page_size: pageSize, keyword: keyword || undefined, status: statusFilter !== 'all' ? statusFilter as VerificationStatus : undefined, } const response = await verificationsApi.getVerifications(params) setVerifications(response.data.data.list || []) setTotal(response.data.data.total || 0) } catch (error) { console.error('Failed to load verifications:', error) setVerifications([]) setTotal(0) } finally { setLoading(false) } }, [page, keyword, statusFilter]) useEffect(() => { loadVerifications() }, [loadVerifications]) const handleViewDetail = async (verification: VerificationListItem) => { setDetailLoading(true) setDetailOpen(true) try { const response = await verificationsApi.getVerificationById(verification.id) setSelectedVerification(response.data.data) } catch (error) { console.error('Failed to load verification detail:', error) setSelectedVerification(null) } finally { setDetailLoading(false) } } const handleOpenReviewDialog = () => { setRejectReason('') setReviewDialogOpen(true) } const handleReview = async (approve: boolean) => { if (!selectedVerification) return if (!approve && !rejectReason.trim()) { alert('请填写拒绝原因') return } setReviewLoading(true) try { await verificationsApi.reviewVerification(selectedVerification.id, { approve, reject_reason: approve ? undefined : rejectReason, }) setReviewDialogOpen(false) setDetailOpen(false) loadVerifications() } catch (error) { console.error('Failed to review verification:', error) alert('审核失败') } finally { setReviewLoading(false) } } const handleSearch = () => { setPage(1) loadVerifications() } const handleRefresh = () => { loadVerifications() } const handlePageChange = (newPage: number) => { setPage(newPage) } const totalPages = Math.ceil(total / pageSize) const getInitials = (name: string) => { return name.slice(0, 2).toUpperCase() } const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', }) } return (

身份认证管理

审核用户身份认证申请

筛选条件 根据条件筛选认证申请
setKeyword(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSearch()} className="max-w-sm" />
认证申请列表 共 {total} 条申请 用户 身份类型 真实姓名 学号/工号 部门 状态 提交时间 操作 {loading ? (

加载中...

) : verifications.length === 0 ? ( 暂无数据 ) : ( verifications.map((verification) => ( handleViewDetail(verification)} >
{getInitials(verification.nickname)}

{verification.nickname}

@{verification.username}

{identityText[verification.identity] || verification.identity} {verification.real_name} {verification.student_id || verification.employee_id || '-'} {verification.department || '-'} {statusText[verification.status]} {formatDate(verification.created_at)} e.stopPropagation()}>
)) )}
{totalPages > 1 && (
)}
{/* 详情对话框 */} 认证详情 查看用户认证申请详情 {detailLoading ? (
) : selectedVerification ? (
{getInitials(selectedVerification.nickname)}

{selectedVerification.nickname}

@{selectedVerification.username}

{statusText[selectedVerification.status]}

身份类型

{identityText[selectedVerification.identity] || selectedVerification.identity}

真实姓名

{selectedVerification.real_name}

{selectedVerification.student_id && (

学号

{selectedVerification.student_id}

)} {selectedVerification.employee_id && (

工号

{selectedVerification.employee_id}

)} {selectedVerification.department && (

部门/院系

{selectedVerification.department}

)}

证明材料

证明材料
{selectedVerification.reviewed_at && ( <>

审核时间

{formatDate(selectedVerification.reviewed_at)}

{selectedVerification.reviewer_name && (

审核人

{selectedVerification.reviewer_name}

)} )} {selectedVerification.reject_reason && (

拒绝原因

{selectedVerification.reject_reason}

)}
{selectedVerification.status === 'pending' && (
)}
) : (

加载失败

)}
{/* 审核对话框 */} 审核认证申请 请选择通过或拒绝该认证申请

拒绝原因(拒绝时必填)