import React, { useEffect, useState, useMemo } from 'react'; import { Card, Select, Button, Space, Spin, Empty, Row, Col, message, DatePicker } from 'antd'; import { Line } from '@ant-design/charts'; import { getIndustryTrend } from '@/services/analysis/industry'; import dayjs from 'dayjs'; import { useRequest } from '@umijs/max'; import { TimeDimension, AnalysisType, IndustryTrendState, IndustryDataItem, ChartConfig } from '@/types/analysis/industry'; import { formatQuarter, formatDateForDisplay, convertApiData } from './utils'; const { Option } = Select; const { RangePicker } = DatePicker; const IndustryTrendPage: React.FC = () => { const [params, setParams] = useState({ timeDimension: '月', type: '岗位发布数量', startTime: dayjs().subtract(5, 'month').format('YYYY-MM'), endTime: dayjs().format('YYYY-MM'), selectedIndustry: '' }); const [allData, setAllData] = useState([]); const [availableIndustries, setAvailableIndustries] = useState([]); const { loading, run: fetchData } = useRequest( async () => { let { startTime, endTime, timeDimension, type } = params; if (timeDimension === '季度') { startTime = formatQuarter(startTime); endTime = formatQuarter(endTime); } return await getIndustryTrend({ timeDimension, type, startTime, endTime }); }, { manual: true, onSuccess: (data) => { const formattedData = convertApiData(data); setAllData(formattedData); const industries = Array.from( new Set(formattedData.map((item: { category: any; }) => item.category)) ).filter(Boolean).sort(); setAvailableIndustries(industries); if (industries.length > 0 && !industries.includes(params.selectedIndustry)) { setParams(p => ({ ...p, selectedIndustry: industries[0] })); } }, onError: () => message.error('数据加载失败') } ); const handleTimeDimensionChange = (value: TimeDimension) => { const now = dayjs(); let newStartTime = ''; if (value === '月') { newStartTime = now.subtract(6, 'month').format('YYYY-MM'); } else if (value === '季度') { newStartTime = now.subtract(6, 'quarter').format('YYYY-Q'); } else { newStartTime = now.subtract(5, 'year').format('YYYY'); } setParams(p => ({ ...p, timeDimension: value, startTime: newStartTime, endTime: value === '月' ? now.format('YYYY-MM') : value === '季度' ? now.format('YYYY-Q') : now.format('YYYY'), selectedIndustry: '' })); }; const handleDateRangeChange = (dates: any, dateStrings: [string, string]) => { if (dates && dates[0] && dates[1]) { setParams(p => ({ ...p, startTime: dateStrings[0], endTime: dateStrings[1] })); } }; const currentIndustryData = useMemo(() => { if (!params.selectedIndustry || allData.length === 0) return []; return allData .filter(item => item.category === params.selectedIndustry) .map(item => ({ ...item, date: formatDateForDisplay(item.date, params.timeDimension) })) .sort((a, b) => { const dateA = a.date.includes('第') ? parseInt(a.date.split('第')[1]) : dayjs(a.date).valueOf(); const dateB = b.date.includes('第') ? parseInt(b.date.split('第')[1]) : dayjs(b.date).valueOf(); return dateA - dateB; }); }, [allData, params.selectedIndustry, params.timeDimension]); const getPickerValue = () => { try { return [ dayjs(params.startTime, params.timeDimension === '年' ? 'YYYY' : params.timeDimension === '季度' ? 'YYYY-Q' : 'YYYY-MM'), dayjs(params.endTime, params.timeDimension === '年' ? 'YYYY' : params.timeDimension === '季度' ? 'YYYY-Q' : 'YYYY-MM') ]; } catch (e) { console.error('日期解析错误:', e); return null; } }; const chartConfig: ChartConfig = { data: currentIndustryData, height: 180, xField: 'date', yField: 'value', seriesField: 'category', xAxis: { type: 'cat', label: { formatter: (text: string) => text, }, }, yAxis: { label: { formatter: (val: string) => `${val}${params.type === '招聘增长率' ? '%' : '个'}`, }, }, tooltip: false, point: { size: 4, shape: 'circle', }, animation: { appear: { animation: 'path-in', duration: 1000, }, }, smooth: true, }; useEffect(() => { fetchData(); }, [params.timeDimension, params.startTime, params.endTime, params.type]); return (
{currentIndustryData.length > 0 ? ( ) : ( )}
); }; export default IndustryTrendPage;