import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { Button, Card, Col, DatePicker, Empty, Row, Segmented, Select, Spin, Statistic, Table, message, } from 'antd'; import { InfoCircleOutlined } from '@ant-design/icons'; import { PageContainer } from '@ant-design/pro-components'; import type { ColumnsType } from 'antd/es/table'; import { getPublicJobFairList } from '@/services/jobfair/publicJobFair'; import { getOutdoorFairList } from '@/services/jobportal/outdoorFair'; import { getFairStatisticsSummary, type FairStatisticsFairItem, type FairStatisticsSummary, type RecruitmentFairType, } from '@/services/jobfair/fairStatistics'; const { RangePicker } = DatePicker; type StatisticsScope = 'single' | 'range'; interface FairOption { value: string; label: string; } const formatDate = (value: any): string | undefined => value && typeof value.format === 'function' ? value.format('YYYY-MM-DD') : undefined; const FairStatistics: React.FC = () => { const [fairType, setFairType] = useState('online'); const [scope, setScope] = useState('single'); const [fairOptions, setFairOptions] = useState([]); const [selectedFairId, setSelectedFairId] = useState(); const [dateRange, setDateRange] = useState(null); const [loadingFairs, setLoadingFairs] = useState(false); const [loadingSummary, setLoadingSummary] = useState(false); const [summary, setSummary] = useState(); const interactionLabel = fairType === 'online' ? '投递岗位数' : '签到数'; const interactionUnit = fairType === 'online' ? '个' : '人次'; const loadFairOptions = useCallback(async (type: RecruitmentFairType) => { setLoadingFairs(true); try { if (type === 'online') { const res = await getPublicJobFairList({ pageNum: 1, pageSize: 1000, jobFairType: '1' }); if (res.code !== 200) { message.error(res.msg || '线上招聘会列表加载失败'); setFairOptions([]); return; } setFairOptions( (res.rows || []).map((item) => ({ value: String(item.jobFairId), label: `${item.jobFairTitle}${item.jobFairStartTime ? `(${item.jobFairStartTime})` : ''}`, })), ); } else { const res = await getOutdoorFairList({ current: 1, pageSize: 1000 }); if (res.code !== 200) { message.error(res.msg || '户外招聘会列表加载失败'); setFairOptions([]); return; } setFairOptions( (res.rows || []).map((item) => ({ value: String(item.id), label: `${item.title}${item.holdTime ? `(${item.holdTime})` : ''}`, })), ); } } catch { message.error('招聘会列表加载失败,请稍后重试'); setFairOptions([]); } finally { setLoadingFairs(false); } }, []); useEffect(() => { setSelectedFairId(undefined); setDateRange(null); setSummary(undefined); loadFairOptions(fairType); }, [fairType, loadFairOptions]); const queryReady = useMemo(() => { if (scope === 'single') return Boolean(selectedFairId); return Boolean(dateRange?.[0] && dateRange?.[1]); }, [dateRange, scope, selectedFairId]); const loadSummary = useCallback(async () => { if (!queryReady) { setSummary(undefined); return; } setLoadingSummary(true); try { const res = await getFairStatisticsSummary({ fairType, fairId: scope === 'single' ? selectedFairId : undefined, startDate: scope === 'range' ? formatDate(dateRange?.[0]) : undefined, endDate: scope === 'range' ? formatDate(dateRange?.[1]) : undefined, }); if (res.code === 200 && res.data) { setSummary(res.data); } else { setSummary(undefined); message.error(res.msg || '统计数据加载失败'); } } catch { setSummary(undefined); message.error('统计数据加载失败,请稍后重试'); } finally { setLoadingSummary(false); } }, [dateRange, fairType, queryReady, scope, selectedFairId]); useEffect(() => { loadSummary(); }, [loadSummary]); const columns: ColumnsType = useMemo( () => [ { title: '招聘会名称', dataIndex: 'fairTitle', ellipsis: true }, { title: '起始时间', dataIndex: 'startTime', width: 180, render: (value) => value || '--' }, { title: '参会单位数', dataIndex: 'companyCount', width: 110, align: 'right' }, { title: '职位数', dataIndex: 'jobCount', width: 90, align: 'right' }, { title: '需求人数', dataIndex: 'demandCount', width: 100, align: 'right' }, { title: interactionLabel, dataIndex: 'interactionCount', width: 120, align: 'right' }, ], [interactionLabel], ); const statisticsCards = [ { title: '参会单位数', value: summary?.companyCount ?? 0, suffix: '家' }, { title: '职位数', value: summary?.jobCount ?? 0, suffix: '个' }, { title: '需求人数', value: summary?.demandCount ?? 0, suffix: '人' }, { title: interactionLabel, value: summary?.interactionCount ?? 0, suffix: interactionUnit }, ]; return ( 统计范围 { setScope(value as StatisticsScope); setSummary(undefined); }} /> {scope === 'single' ? (