import { useEffect, useState, useCallback, useMemo } from 'react'; import { Spin } from 'antd'; import { ApexOptions } from 'apexcharts'; import ReactApexChart from 'react-apexcharts'; import { MonthlySums, Result, ChartOneState } from './type'; import dayjs from 'dayjs'; const VisitorsStatisChat = () => { const [result, setResult] = useState(null); const [scope, setScope] = useState<"day" | "month" | "year">("day"); const [startDate, setStartDate] = useState(dayjs(new Date()).subtract(7, "day").format("YYYY/MM/DD")); const [endDate, setEndDate] = useState(dayjs(new Date()).format("YYYY/MM/DD")); const [loading, setLoading] = useState(false); // Echarts相关配置 const [options, setOptions] = useState({ legend: { show: false, position: 'top', horizontalAlign: 'left', }, colors: ['#3C50E0', '#80CAEE'], chart: { fontFamily: 'Satoshi, sans-serif', height: 335, type: 'area', dropShadow: { enabled: true, color: '#623CEA14', top: 10, blur: 4, left: 0, opacity: 0.1, }, toolbar: { show: false, }, }, responsive: [ { breakpoint: 1024, options: { chart: { height: 300, }, }, }, { breakpoint: 1366, options: { chart: { height: 350, }, }, }, ], stroke: { width: [2, 2], curve: 'straight', }, grid: { xaxis: { lines: { show: true, }, }, yaxis: { lines: { show: true, }, }, }, dataLabels: { enabled: false, }, markers: { size: 4, colors: '#fff', strokeColors: ['#3056D3', '#80CAEE'], strokeWidth: 3, strokeOpacity: 0.9, strokeDashArray: 0, fillOpacity: 1, discrete: [], hover: { size: undefined, sizeOffset: 5, }, }, xaxis: { type: 'category', categories: [], axisBorder: { show: false, }, axisTicks: { show: false, }, }, yaxis: { title: { style: { fontSize: '0px', }, }, }, }); // 核心数据 const [state, setState] = useState({ series: [ { name: '访客数量', data: [], }, { name: 'IP数量', data: [], }, ], }); // 获取统计数据 const getDataList = useCallback(async () => { setLoading(true); const siteId = import.meta.env.VITE_BAIDU_TONGJI_SITE_ID; const token = import.meta.env.VITE_BAIDU_TONGJI_ACCESS_TOKEN; const response = await fetch(`/api/rest/2.0/tongji/report/getData?access_token=${token}&site_id=${siteId}&start_date=${startDate}&end_date=${endDate}&metrics=pv_count%2Cip_count&method=overview%2FgetTimeTrendRpt`); const data = await response.json(); const { result } = data; setResult(result); setLoading(false); }, [startDate, endDate]); useEffect(() => { getDataList(); }, [getDataList]); // 切换不同范围的数据 const scopeData = useMemo(() => { if (!result?.items?.length) return { categories: [], series: [[], []] }; let categories = []; let pvList = []; let ipList = []; switch (scope) { case "day": categories = result.items[0].map((item: string[]) => { const year = new Date().getFullYear() + "/"; return item[0].replace(year, ""); }); pvList = result.items[1].map((item: number[]) => item[0]); ipList = result.items[1].map((item: number[]) => item[1]); break; case "month": const datesArray: string[][] = result.items[0]; const valuesArray: (string | number)[][] = result.items[1]; const monthlySums: MonthlySums = {}; datesArray.forEach((dateArray, index) => { const date: string = dateArray[0]; const [year, month, day] = date.split('/'); if (!monthlySums[month]) { monthlySums[month] = { pv: 0, ip: 0 }; } const pair = valuesArray[index]; if (pair.length === 2) { const firstValue = parseFloat(pair[0] as string); const secondValue = parseFloat(pair[1] as string); if (!isNaN(firstValue) && !isNaN(secondValue)) { monthlySums[month].pv += firstValue; monthlySums[month].ip += secondValue; } } }); categories = Object.keys(monthlySums); pvList = Object.values(monthlySums).map(item => item.pv); ipList = Object.values(monthlySums).map(item => item.ip); break; case "year": const yearlySums: { [year: string]: { pv: number, ip: number } } = {}; result.items[0].forEach((dateArray: string[], index: number) => { const date: string = dateArray[0]; const [year, month, day] = date.split('/'); if (!yearlySums[year]) { yearlySums[year] = { pv: 0, ip: 0 }; } const pair = result.items[1][index]; if (pair.length === 2) { const firstValue = parseFloat(pair[0] + ''); const secondValue = parseFloat(pair[1] + ''); if (!isNaN(firstValue) && !isNaN(secondValue)) { yearlySums[year].pv += firstValue; yearlySums[year].ip += secondValue; } } }); // 删除没有数据的年份 Object.keys(yearlySums).forEach(year => { if (yearlySums[year].pv === 0 && yearlySums[year].ip === 0) { delete yearlySums[year]; } }); categories = Object.keys(yearlySums); pvList = Object.values(yearlySums).map(item => item.pv); ipList = Object.values(yearlySums).map(item => item.ip); break; } return { categories, series: [pvList, ipList] }; }, [result, scope]); // 当数据发生变化时,更新图表选项和状态 useEffect(() => { setOptions((data) => ({ ...data, xaxis: { ...options.xaxis, categories: scopeData.categories } })); setState((prevState) => ({ ...prevState, series: [ { name: '访客数量', data: scopeData.series[0], }, { name: 'IP数量', data: scopeData.series[1], }, ], })); }, [scopeData]); // 处理范围变更并相应地更新日期范围 const handleScopeChange = (newScope: "day" | "month" | "year") => { setScope(newScope); switch (newScope) { case "day": setStartDate(dayjs(new Date()).subtract(7, "day").format("YYYY/MM/DD")); break; case "month": const year = new Date().getFullYear() + ""; setStartDate(year + "/01/01"); break; case "year": setStartDate(dayjs(new Date()).subtract(5, "year").format("YYYY/MM/DD")); break; } }; return (

访客(UV)

IP

); }; export default VisitorsStatisChat;