| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- import React, { useState } from 'react';
- import {
- Button, Form, Select, Card, Typography, DatePicker
- } from 'antd';
- import {
- useQuery,
- } from '@tanstack/react-query';
- import dayjs from 'dayjs';
- import { Line } from "@ant-design/plots";
- import 'dayjs/locale/zh-cn';
- import { MonitorChartsAPI } from './api/index.ts';
- interface ChartTooltipInfo {
- items: Array<Record<string, any>>;
- title: string;
- }
- // 告警数据变化图表页面
- export const AlertTrendChartPage = () => {
- const [timeRange, setTimeRange] = useState<[dayjs.Dayjs, dayjs.Dayjs]>([
- dayjs().subtract(1, 'day').startOf('day'),
- dayjs().endOf('day')
- ]);
- const [dimension, setDimension] = useState<'hour' | 'day' | 'month'>('hour');
-
- const { data: alarmData, isLoading, refetch } = useQuery({
- queryKey: ['adminZichanAlarm', timeRange, dimension],
- queryFn: async () => {
- const params = {
- created_at_gte: timeRange[0].format('YYYY-MM-DD HH:mm:ss'),
- created_at_lte: timeRange[1].format('YYYY-MM-DD HH:mm:ss'),
- dimension
- };
-
- // const res = await axios.get<AlarmChartData[]>(`${API_BASE_URL}/big/zichan_alarm_chart`, { params });
- const res = await MonitorChartsAPI.fetchAlarmData(params);
- return res;
- }
- });
-
- const { Title } = Typography;
- const { RangePicker } = DatePicker;
-
- const handleSearch = () => {
- refetch();
- };
-
- return (
- <div>
- <Title level={2}>告警数据趋势</Title>
-
- <Card>
- <Form layout="inline" style={{ marginBottom: '16px' }}>
- <Form.Item label="时间范围">
- <RangePicker
- value={timeRange}
- onChange={(dates) => dates && setTimeRange(dates as [dayjs.Dayjs, dayjs.Dayjs])}
- showTime
- />
- </Form.Item>
- <Form.Item label="时间维度">
- <Select
- value={dimension}
- onChange={setDimension}
- options={[
- { label: '小时', value: 'hour' },
- { label: '天', value: 'day' },
- { label: '月', value: 'month' }
- ]}
- style={{ width: '100px' }}
- />
- </Form.Item>
- <Form.Item>
- <Button type="primary" onClick={handleSearch}>查询</Button>
- </Form.Item>
- </Form>
-
- <div style={{ height: '500px' }}>
- {!isLoading && alarmData && (
- <Line
- data={alarmData}
- xField="time_interval"
- yField="total_devices"
- smooth={true}
- color="#36cfc9"
- label={{
- position: 'top',
- style: {
- fill: '#000',
- fontSize: 12,
- fontWeight: 500,
- },
- text: (items: Record<string, any>) => {
- const value = items['total_devices'];
-
- // if (value === 0) return null;
-
- // const maxValue = Math.max(...(alarmData || []).map(item => item.total_devices));
-
- // if (value < maxValue * 0.3 && alarmData && alarmData.length > 8) return null;
-
- return `${items['time_interval']}\n(${value})`;
- },
- transform: [{ type: 'overlapDodgeY' }],
- }}
- point={{
- size: 5,
- shape: 'diamond',
- }}
- xAxis={{
- label: {
- style: {
- fill: '#000',
- },
- autoHide: true,
- autoRotate: true,
- },
- }}
- yAxis={{
- label: {
- style: {
- fill: '#000',
- },
- },
- }}
- autoFit={true}
- interaction={{
- tooltip: {
- render: (_: unknown, { items, title }: ChartTooltipInfo) => {
- if (!items || items.length === 0) return '';
-
- // 获取当前选中项的数据
- const item = items[0];
-
- // 根据value找到对应的完整数据项
- const fullData = alarmData?.find(d => d.total_devices === item.value);
- if (!fullData) return '';
-
- return `<div class="bg-white p-2 rounded">
- <div class="flex items-center">
- <div class="w-3 h-3 rounded-full mr-2" style="background:${item.color}"></div>
- <span class="font-semibold text-gray-900">${fullData.time_interval}</span>
- </div>
- <p class="text-sm text-gray-800">数量: ${item.value}</p>
- </div>`;
- }
- }
- }}
- />
- )}
- </div>
- </Card>
- </div>
- );
- };
|