/**
 * 走influxdb版本的,不抽稀通过zoom和unit传空字符串实现;
 * 非influxdb版本的接口,使用isDilute=false实现;
 * 建议:不抽稀的时候,传isDilute=false&zoom=''&unit=''
 * */
import React, {useContext, useEffect, useMemo, useState, useCallback, useRef} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import {
    Checkbox,
    ConfigProvider,
    DatePicker,
    Radio,
    Select,
    Spin,
    Tabs,
    Tooltip,
    Button,
    message,
    Progress,
} from 'antd';
import {
    CloseCircleFilled,
    PlusCircleOutlined,
    QuestionCircleFilled,
    DownloadOutlined,
} from '@ant-design/icons';
import moment from 'moment';
import _ from 'lodash';
import TimeRangePicker from '@wisdom-components/timerangepicker';
import PandaEmpty from '@wisdom-components/empty';
import {
    getHistoryInfo,
    getDeviceAlarmScheme,
    getExportDeviceHistoryUrl,
    getDictionaryInfoAll,
    getPointAddress,
    getPointAddressEntry, getPredicateSensor,
} from './apis';
import SingleChart from './SingleChart';
import GridChart from './GridChart';
import BIStyles from './indexForBI.less';
import {globalConfig} from 'antd/lib/config-provider';
import {getSensorType} from './apis/index';
import {ExportExcel} from '@wisdom-components/exportexcel';

import VirtualTable from './VirtualTable';

const {RangePicker} = DatePicker;
const {Option} = Select;

const startFormat = 'YYYY-MM-DD 00:00:00';
const endFormat = 'YYYY-MM-DD 23:59:59';
const timeFormat = 'YYYY-MM-DD HH:mm:ss';
const dateFormat = 'YYYYMMDD';

const timeList = [
    {
        key: 'twelveHours',
        name: '近12小时',
    },
    {
        key: 'roundClock',
        name: '近24小时',
    },
    {
        key: 'yesterday',
        name: '昨日',
    },
    {
        key: 'oneWeek',
        name: '近1周',
    },
    {
        key: 'oneMonth',
        name: '近1月',
    },
];
const predicateMap = {
    twelveHours: 12,
    roundClock: 24,
    oneWeek: 24,
    oneMonth: 24
}

// 同期对比 日 快捷按钮
const shortcutsForDay = [
    {
        label: '近3天',
        value: '近3天',
    },
    {
        label: '近7天',
        value: '近7天',
    },
    /*    {
                label: '去年同期',
                value: '去年同期',
            }*/
];
// 同期对比 月 快捷按钮
const shortcutsForMonth = [
    {
        label: '近3月',
        value: '近3月',
    },
    {
        label: '近6月',
        value: '近6月',
    },
    /*    {
                label: '去年同期',
                value: '去年同期',
            }*/
];

const CheckboxData = [
    {
        key: 'curveCenter',
        label: '曲线居中',
        checked: false,
        showInCurve: true,
        showInTable: false,
    },
    {
        key: 'chartGrid',
        label: '图表网格',
        checked: true,
        showInCurve: true,
        showInTable: false,
    },
    {
        key: 'ignoreOutliers',
        label: '去除异常值',
        type: 'updateIgnoreOutliers',
        checked: false,
        showInCurve: true,
        showInTable: true,
        tooltip: '采用递推平均滤波法(滑动平均滤波法)对采样数据中的异常离群值进行识别与去除。',
        hasSub: true,
    },
    {
        key: 'dataThin',
        label: '数据抽稀',
        type: 'updateDataThin',
        checked: true,
        showInCurve: false,
        showInTable: true,
    }
];

const timeIntervalList = [
    {
        key: '1min',
        zoom: '1',
        unit: 'min',
        name: '1分钟',
    },
    {
        key: '5',
        zoom: '5',
        unit: 'min',
        name: '5分钟',
    },
    {
        key: '10',
        zoom: '10',
        unit: 'min',
        name: '10分钟',
    },
    {
        key: '30',
        zoom: '30',
        unit: 'min',
        name: '30分钟',
    },
    {
        key: '1',
        zoom: '1',
        unit: 'h',
        name: '1小时',
    },
    {
        key: '2',
        zoom: '2',
        unit: 'h',
        name: '2小时',
    },
    {
        key: '4',
        zoom: '4',
        unit: 'h',
        name: '4小时',
    },
    {
        key: '6',
        zoom: '6',
        unit: 'h',
        name: '6小时',
    },
    {
        key: '12',
        zoom: '12',
        unit: 'h',
        name: '12小时',
    },
    {
        key: '24',
        zoom: '24',
        unit: 'h',
        name: '24小时',
    },
];

const handleTimeForPredicate = (key, start, end) => {
    let t = predicateMap[key] || 0;
    return moment(end).add(t, 'hours').format(timeFormat);
};
const updateTime = (key, predicate) => {
    let start = '';
    let end = '';

    if (Array.isArray(key)) {
        start = moment(key[0]).format(timeFormat);
        end = moment(key[1]).format(timeFormat);
    } else {
        switch (key) {
            case 'twelveHours':
                start = moment().subtract(12, 'hour').format(timeFormat);
                end = moment().format(timeFormat);
                break;
            case 'roundClock':
                start = moment().subtract(24, 'hour').format(timeFormat);
                end = moment().format(timeFormat);
                break;
            case 'yesterday':
                start = moment().subtract(1, 'days').format('YYYY-MM-DD 00:00:00');
                end = moment().subtract(1, 'days').format('YYYY-MM-DD 23:59:59');
                break;
            case 'oneWeek':
                start = moment().subtract(7, 'day').format(timeFormat);
                end = moment().format(timeFormat);
                break;
            case 'oneMonth':
                start = moment().subtract(30, 'day').format(timeFormat);
                end = moment().format(timeFormat);
                break;
        }
    }

    if (predicate) {
        end = handleTimeForPredicate(key, end)
    }
    return [
        {
            dateFrom: start,
            dateTo: end,
        },
    ];
};

const DefaultDatePicker = (value) => [
    {
        key: 1,
        value: moment(),
    },
    {
        key: 2,
        value: moment().subtract(1, value),
    },
];

const handleBatchTime = (arr, cOption) => {
    let newArr = [];
    arr.forEach((child) => {
        if (child.value) {
            newArr.push({
                dateFrom: moment(child.value).startOf(cOption).format(startFormat),
                dateTo: moment(child.value).endOf(cOption).format(endFormat),
            });
        }
    });
    newArr = _.uniqWith(newArr, _.isEqual); // 去掉重复日期时间
    return newArr;
};
const handleFakeData = (dateRange, deviceParams) => {
    let dateFrom = dateRange[0].dateFrom;
    let dateTo = dateRange[0].dateTo;
    return deviceParams.reduce((final, cur) => {
        let _arr = cur.sensors.split(',');
        _arr.forEach(sensor => {
            final.push({
                dataModel: [
                    {pt: dateFrom, pv: null},
                    {pt: dateTo, pv: null}
                ],
                dateFrom,
                dateTo,
                deviceCode: cur.deviceCode,
                deviceType: cur.deviceType,
                sensorName: sensor,
                equipmentName: '',
                stationCode: cur.deviceCode
            })
        })
        return final;
    }, [])
}
const timeColumn = {
    title: '采集时间',
    dataIndex: 'time',
    key: 'time',
    width: 170,
    ellipsis: true,
    align: 'center',
    sorter: true,
    // sortOrder:['descend','ascend']
};
const OriginMaxDays = 31; // 原始曲线请求数据的最大天数
const CharacteristicMaxDays = null; // 特征曲线或者其他曲线的最大天数
const HistoryView = (props) => {
    const [completeInit, setCompleteInit] = useState(false);
    const {getPrefixCls} = useContext(ConfigProvider.ConfigContext);
    const prefixCls = getPrefixCls('history-view');
    const {
        title,
        grid,
        defaultChecked,
        tableProps,
        deviceParams,
        defaultModel,
        showModels,
        needMarkLine,
        defaultDate,
        theme = "Normal"
    } = props;
    if (theme === 'Normal') import('./index.less');
    if (theme === 'BI') import('./indexForBI.less');
    const isBoxPlots =
        deviceParams?.length === 1 && deviceParams?.[0]?.sensors?.split(',').length === 1;
    const [loading, setLoading] = useState(null);
    const [activeTabKey, setActiveTabKey] = useState(defaultModel);

    // 时间模式: 自定义模式/同期对比模式
    const [timeValue, setTimeValue] = useState('customer');

    // 自定义模式
    const [customerChecked, setCustomerChecked] = useState(defaultChecked); // 时间快速选择类型值
    const [customerTime, setCustomerTime] = useState(); // 自定义时间选择值

    // 同期对比模式
    const [contrastOption, setContrastOption] = useState('day'); // 对比时间类型: 日/月
    const [datePickerArr, setDatePickerArr] = useState(DefaultDatePicker(defaultDate)); // 对比时间段配置值
    const [checkboxData, setCheckboxData] = useState(() => [...CheckboxData]); // 曲线设置项
    const [dataThinKey, setDataThinKey] = useState(
        timeIntervalList[0].key === '1min' ? timeIntervalList[1].key : timeIntervalList[0].key,
    ); // 曲线抽稀时间设置
    const [algorithmValue, setAlgorithmValue] = useState(1);

    const [columns, setColumns] = useState([]);
    const [tableData, setTableData] = useState([]);
    const [timeOrder, setTimeOrder] = useState('descend');
    const [chartType, setChartType] = useState('lineChart');
    const [showBoxOption, setShowBoxOption] = useState(true);
    const [lineDataType, setLineDataType] = useState('特征曲线');
    // 同期对比快捷键
    // shortcutsValue
    // onShortcutsChange
    const [shortcutsValue, setShortcutsValue] = useState('');
    const [shortcutsDatePickerArr, setShortcutsDatePickerArr] = useState([]);
    const [percent, setPercent] = useState(0);
    // 频率指标特殊业务
    const [special1, setSpecial1] = useState(null);
    const [allPointAddress, setAllPointAddress] = useState([]);
    //查询所有sensorType
    const [allSensorType, setAllSensorType] = useState([]);
    const [isSingleStatusSensor, setIsSingleStatusSensor] = useState(false);
    const [predicateDevice, setPredicateDevice] = useState(null);
    const [predicateData, setPredicateData] = useState([]);
    const [predicateTime, setPredicateTime] = useState(null);
    // 需要处理默认数据,确保图表能够一直显示坐标轴。用来存储当前的请求状态。
    const emptyOrError = useRef({
        empty: true,
        error: true
    })
    // 这部分功能有问题,等待解决后上线 2024年3月13日
    const [discreteDeviceType, setDiscreteDeviceType] = useState(['水厂'])
    // 历史数据相关的特征描述
    const deviceConfig = useRef({
        oneDevice: deviceParams.length === 1, //单设备
        oneSensor:
            [
                ...new Set(
                    deviceParams.reduce((final, cur) => {
                        let _sensors = cur.sensors.split(',');
                        return final.concat(_sensors);
                    }, []),
                ),
            ].length === 1, // 单指标
    });
    // 表格虚拟列表
    const tableRef = useRef();
    // 选择的时间范围值
    const dateRange = useMemo(() => {
        if (timeValue === 'customer') {
            return updateTime(customerChecked || customerTime, predicateDevice);
        } else {
            let _dateArr = shortcutsValue ? shortcutsDatePickerArr : datePickerArr;
            return handleBatchTime(_dateArr, contrastOption);
        }
    }, [contrastOption, customerChecked, customerTime, datePickerArr, timeValue, shortcutsValue]);
    useEffect(() => {
        let _diffDays = moment(dateRange[0].dateTo).diff(dateRange[0].dateFrom, 'days');
        if (_diffDays > 7 && dataThinKey === '1min') {
            setDataThinKey(timeIntervalList[1].key);
        }
    }, [dateRange]);
    const [dates, setDates] = useState(null);
    const [chartDataSource, setChartDataSource] = useState(handleFakeData(dateRange, deviceParams) ?? []);
    const configDependence = checkboxData
        .filter((item) => ['curveCenter', 'chartGrid'].indexOf(item.key) === -1)
        .map((item) => item.checked)
        .join(',');
    // 数据配置
    const dataConfig = useMemo(() => {
        const initial = {
            ignoreOutliers: false,
            dataThin: false,
            zoom: '', // 数据抽稀时间
            unit: '', // 数据抽稀时间单位
        };
        // 曲线居中,过滤异常值,数据抽稀
        const config = checkboxData.reduce(
            (pre, item) => (item.key !== 'curveCenter' && (pre[item.key] = item.checked), pre),
            initial,
        );
        // 数据抽稀时间单位
        const dataThin = timeIntervalList.find((item) => item.key === dataThinKey);
        config.zoom = activeTabKey === 'curve' ? '' : dataThin?.zoom ?? '';
        config.unit = activeTabKey === 'curve' ? '' : dataThin?.unit ?? '';
        config.dataThin = activeTabKey === 'curve' ? true : config.dataThin; // 曲线强制抽稀

        return config;
    }, [configDependence, dataThinKey, activeTabKey]);

    // 图表居中
    const [curveCenter, chartGrid] = useMemo(() => {
        const curveCenter = checkboxData.find((item) => item.key === 'curveCenter')?.checked;
        const chartGrid = checkboxData.find((item) => item.key === 'chartGrid')?.checked;
        return [curveCenter, chartGrid];
    }, [checkboxData]);

    // 自定义模式: 快速选择
    const onCustomerTimeChange = (key) => {
        setCustomerChecked(key);
        setPredicateTime(predicateMap[key]);
        !!customerTime && setCustomerTime(null);
    };

    // 自定义模式: 自定义时间选择
    const onCustomerRangeChange = (value) => {
        if (!value) {
            // 时间清空,回到默认时间选择
            setCustomerChecked(defaultChecked);
            setCustomerTime(value);
        } else {
            setCustomerChecked(null);
            let diffDays = moment(value[1]).diff(moment(value[0]), 'days');
            if (diffDays > OriginMaxDays && lineDataType === '原始曲线') {
                setLineDataType('特征曲线');
                message.info('时间区间超过7天,已切换为特征曲线');
            }
            setCustomerTime(value);
        }
    };

    // 同期对比模式: 选择(日/月)
    const onContrastChange = (value) => {
        if (value === 'month') {
            if (lineDataType === '原始曲线')
                message.info('月模式数据量较大,不支持原始曲线模式,已切换为特征曲线');
            setLineDataType('特征曲线');
        }
        setShortcutsValue('');
        setContrastOption(value);
        // 模式为日时,默认对比时间根据defaultDate判断 是昨天、上月、还是去年
        setDatePickerArr([...DefaultDatePicker(value === 'day' && defaultDate ? defaultDate : value)]);
    };

    // 同期对比模式: 时间段选择
    const onContrastPickerChange = (date, dateString, item) => {
        // 操作时间就清除掉快捷键选用状态
        setShortcutsValue('');
        const arr = [...datePickerArr];
        arr.forEach((child) => {
            if (child.key === item.key) {
                child.value = date;
            }
        });
        setDatePickerArr(arr);
    };

    // 同期对比模式: 新增日期选择组件
    const handleAddDatePicker = () => {
        // 操作时间就清除掉快捷键选用状态
        setShortcutsValue('');
        setDatePickerArr([
            ...datePickerArr,
            {
                key: datePickerArr[datePickerArr.length - 1].key + 1,
                value: '',
            },
        ]);
    };

    // 同期对比模式: 删除日期选择组件
    const handleDeleteDatePicker = (index) => {
        // 操作时间就清除掉快捷键选用状态
        setShortcutsValue('');
        const arr = [...datePickerArr];
        arr.splice(index, 1);
        setDatePickerArr(arr);
    };

    // 时间设置切换(自定义/同期对比)
    const onTimeSetChange = (e) => {
        // 操作时间就清除掉快捷键选用状态
        setShortcutsValue('');
        if (e.target.value === 'customer') {
            setLineDataType('特征曲线');
            setShortcutsValue('');
        }
        setTimeValue(e.target.value);
        if (e.target.value === 'contrast') {
            // 同期对比
            onContrastChange(contrastOption);
            setShowBoxOption(false);
            setChartType('lineChart');
            onCheckboxChange({target: {value: false}}, 'chartType');
            onCheckboxChange({target: {value: false}}, 'ignoreOutliers');
        } else {
            // 自定义
            // 不需要处理
            setShowBoxOption(true);
            onCheckboxChange({target: {value: true}}, 'chartType');
        }
    };
    const onShortcutsChange = (e) => {
        let _val = e.target.value;
        setShortcutsValue(_val);
        let _arr = [];
        switch (_val) {
            case '近3天':
                _arr = [
                    {key: 1, value: moment()},
                    {key: 2, value: moment().subtract(1, 'days')},
                    {key: 3, value: moment().subtract(2, 'days')},
                ];
                break;
            case '近7天':
                _arr = [
                    {key: 1, value: moment()},
                    {key: 2, value: moment().subtract(1, 'days')},
                    {key: 3, value: moment().subtract(2, 'days')},
                    {key: 4, value: moment().subtract(3, 'days')},
                    {key: 5, value: moment().subtract(4, 'days')},
                    {key: 6, value: moment().subtract(5, 'days')},
                    {key: 7, value: moment().subtract(6, 'days')},
                ];
                break;
            case '近3月':
                _arr = [
                    {key: 1, value: moment()},
                    {key: 2, value: moment().subtract(1, 'months')},
                    {key: 3, value: moment().subtract(2, 'months')},
                ];
                break;
            case '近6月':
                _arr = [
                    {key: 1, value: moment()},
                    {key: 2, value: moment().subtract(1, 'months')},
                    {key: 3, value: moment().subtract(2, 'months')},
                    {key: 4, value: moment().subtract(3, 'months')},
                    {key: 5, value: moment().subtract(4, 'months')},
                    {key: 6, value: moment().subtract(5, 'months')},
                ];
                break;
        }
        setShortcutsDatePickerArr(_arr);
    };
    const renderTimeOption = useMemo(() => {
        return (
            <div className={classNames(`${prefixCls}-date`)}>
                <div className={classNames(`${prefixCls}-label`)}>时间选择</div>
                <Radio.Group value={timeValue} onChange={onTimeSetChange}>
                    <Radio.Button value="customer">自定义</Radio.Button>
                    {!grid ? <Radio.Button value="contrast">同期对比</Radio.Button> : ''}
                </Radio.Group>
                {timeValue === 'customer' && ( // 自定义
                    <>
                        <TimeRangePicker
                            format={'YYYY-MM-DD HH:mm'}
                            onChange={onCustomerTimeChange}
                            value={customerChecked}
                            dataSource={timeList}
                        />
                        <RangePicker
                            getPopupContainer={trigger => trigger.parentElement}
                            format={'YYYY-MM-DD HH:mm'}
                            className={classNames(`${prefixCls}-custime-customer`)}
                            onChange={onCustomerRangeChange}
                            value={dates || customerTime}
                            onCalendarChange={(val) => {
                                setDates(val);
                            }}
                            onOpenChange={(open) => {
                                if (open) {
                                    setDates([null, null]);
                                } else {
                                    setDates(null);
                                }
                            }}
                            disabledDate={(current) => {
                                if (timeValue !== 'customer') return false;
                                let _days = lineDataType === '原始曲线' ? OriginMaxDays : CharacteristicMaxDays;
                                if (!dates) {
                                    return false;
                                }
                                if (!_days) return false;
                                const tooLate = dates[0] && current.diff(dates[0], 'days') > _days;
                                const tooEarly = dates[1] && dates[1].diff(current, 'days') > _days;
                                return !!tooEarly || !!tooLate;
                            }}
                            showTime={{
                                format: 'YYYY-MM-DD HH:mm',
                                minuteStep: 10,
                            }}
                        />
                    </>
                )}
                {timeValue === 'contrast' && ( // 同期对比
                    <>
                        <Select value={contrastOption} style={{width: 60}} onChange={onContrastChange}>
                            <Option value="day">日</Option>
                            <Option value="month" disabled={lineDataType === '原始曲线'}>
                                月
                            </Option>
                        </Select>
                        {/*增加快捷日期*/}
                        {deviceParams?.length === 1 && deviceParams?.[0]?.sensors?.split(',').length === 1 ? (
                            <Radio.Group value={shortcutsValue} onChange={onShortcutsChange}>
                                {(contrastOption === 'day' ? shortcutsForDay : shortcutsForMonth).map((item) => {
                                    return <Radio.Button value={item.value}>{item.label}</Radio.Button>;
                                })}
                            </Radio.Group>
                        ) : (
                            ''
                        )}
                        {datePickerArr.map((child, index) => (
                            <div key={child.key} className={classNames(`${prefixCls}-contrast-list`)}>
                                <div className={classNames(`${prefixCls}-contrast-wrap`)}>
                                    <DatePicker
                                        key={child.key}
                                        picker={contrastOption === 'day' ? undefined : contrastOption}
                                        value={child.value}
                                        onChange={(date, dateString) => onContrastPickerChange(date, dateString, child)}
                                        style={{width: 130, border: !shortcutsValue ? '1px solid #1890ff' : ''}}
                                    />
                                    {datePickerArr.length > 2 && (
                                        <div
                                            className={classNames(`${prefixCls}-contrast-delete`)}
                                            onClick={() => handleDeleteDatePicker(index)}
                                        >
                                            <CloseCircleFilled/>
                                        </div>
                                    )}
                                </div>
                                {index < datePickerArr.length - 1 && (
                                    <div className={classNames(`${prefixCls}-contrast-connect`)}>与</div>
                                )}
                            </div>
                        ))}
                        {datePickerArr.length < 4 && <PlusCircleOutlined onClick={handleAddDatePicker}/>}
                    </>
                )}
            </div>
        );
    }, [
        timeValue,
        customerChecked,
        lineDataType,
        datePickerArr,
        deviceParams,
        dates,
        customerTime,
        chartDataSource,
    ]);

    // 曲线设置项选择/取消
    const onCheckboxChange = (e, key, showJustLine) => {
        let data = [...checkboxData];
        let _index1 = data.findIndex((item) => item.key === 'ignoreOutliers'); // 仅查看曲线会在勾选了数据滤波后展示
        data.forEach((item) => {
            if (item.key === key) {
                item.checked = e.target.checked;
            }
        });
        if (key === 'ignoreOutliers') {
            data[_index1].showInCurve = true;
        }

        if (key === 'chartType') {
            data[_index1].showInCurve = e.target.value;
            data[_index1].checked = false;
            // data[_index].showInCurve = false;
            // data[_index].checked = false;
        }
        setCheckboxData(data);
    };

    // 数据抽稀时间间隔
    const onTimeIntervalChange = (value) => {
        setDataThinKey(value);
    };
    // 切换数据类型
    const switchLineDataType = (e) => {
        let _val = e.target.value;
        let _startDate = dateRange[0]?.dateFrom;
        let _endDate = dateRange[0]?.dateTo;
        let diffDays = moment(_endDate).diff(moment(_startDate), 'days');
        if (_val === '原始曲线' && diffDays > OriginMaxDays) {
            message.info('查阅原始曲线时,需选择小于或等于31天的时间间隔,已自动切换为近一月');
            setCustomerChecked('oneMonth');
        }
        if (_val === '原始曲线') {
            setContrastOption('day');
        }
        setLineDataType(_val);
    };
    const renderCheckbox = (child, showJustLine) => {
        const curveAccess = activeTabKey === 'curve' && child.showInCurve;
        const tableAccess = activeTabKey === 'table' && child.showInTable;
        const gridOptions = ['curveCenter'];

        if (grid && curveAccess && gridOptions.indexOf(child.key) === -1) return null;
        return (
            (curveAccess || tableAccess) && (
                <>
                    <Checkbox checked={child.checked} onChange={(e) => onCheckboxChange(e, child.key)}>
                        {child.label}
                    </Checkbox>
                    {child.tooltip && (
                        <Tooltip title={child.tooltip}>
                            <QuestionCircleFilled className={`${prefixCls}-question`}/>
                        </Tooltip>
                    )}
                    {child.hasSub && child.checked && false ? (
                        <Select
                            style={{width: 80, marginLeft: 10}}
                            value={algorithmValue}
                            onChange={(e) => setAlgorithmValue(e)}
                        >
                            <Option value={1}>低</Option>
                            <Option value={5}>中</Option>
                            <Option value={10}>高</Option>
                        </Select>
                    ) : (
                        ''
                    )}
                </>
            )
        );
    };

    const renderCurveOption = (isChart, isSingle, isStatus) => {
        return (
            <div
                className={classNames(`${prefixCls}-cover`)}
                style={isChart && isSingle ? {width: '100%'} : {}}
            >
                {isChart && !isStatus ? (
                    <>
                        <div className={classNames(`${prefixCls}-label`)}>曲线选择</div>
                        <div className={`${prefixCls}-cover-item`}>
                            <Radio.Group value={lineDataType} onChange={switchLineDataType}>
                                <Radio.Button value={'特征曲线'}>特征曲线</Radio.Button>
                                <Radio.Button value={'原始曲线'}>原始曲线</Radio.Button>
                            </Radio.Group>
                            <Tooltip title={'原始曲线数据量较大,单次查询最多展示1万条数据'}>
                                <QuestionCircleFilled
                                    style={{marginLeft: 6}}
                                    className={`${prefixCls}-question`}
                                />
                            </Tooltip>
                        </div>
                    </>
                ) : (
                    ''
                )}
                {isChart && isSingle && showBoxOption && !isStatus && !grid ? (
                    <>
                        {lineDataType !== '原始曲线' ? (
                            <>
                                <div style={{marginLeft: 7}} className={classNames(`${prefixCls}-label`)}>
                                    曲线形态
                                </div>
                                <Radio.Group
                                    value={chartType}
                                    style={{marginRight: 16}}
                                    onChange={(e) => {
                                        let _value = e.target.value;
                                        setChartType(_value);
                                        onCheckboxChange({target: {value: _value !== 'boxChart'}}, 'chartType');
                                    }}
                                >
                                    <Radio.Button value={'lineChart'}>线形图</Radio.Button>
                                    <Radio.Button value={'boxChart'}>箱线图</Radio.Button>
                                </Radio.Group>
                            </>
                        ) : (
                            ''
                        )}
                    </>
                ) : (
                    ''
                )}
                {!isStatus ? (
                    <>
                        <div className={classNames(`${prefixCls}-label`)}>
                            {activeTabKey !== 'table' ? '曲线设置' : '表格设置'}
                        </div>
                        {checkboxData.map((child) => {
                            const box = renderCheckbox(child, isChart && isSingle);
                            if (!box) return null;
                            return (
                                <div key={child.key} className={`${prefixCls}-cover-item`}>
                                    {box}
                                </div>
                            );
                        })}
                        {activeTabKey === 'table' && (
                            <Select
                                value={dataThinKey}
                                style={{width: 90}}
                                onChange={onTimeIntervalChange}
                                disabled={!dataConfig.dataThin}
                                getPopupContainer={trigger => trigger.parentElement}
                            >
                                {timeIntervalList
                                    .filter((item) => {
                                        let _diffDays = moment(dateRange[0].dateTo).diff(dateRange[0].dateFrom, 'days');
                                        return !(_diffDays > 7 && item.key === '1min');
                                    })
                                    .map((child) => {
                                        return (
                                            <Option key={child.key} unit={child.unit} value={child.key}>
                                                {child.name}
                                            </Option>
                                        );
                                    })}
                            </Select>
                        )}
                    </>
                ) : (
                    ''
                )}
            </div>
        );
    };

    const exportExcelBtn = () => {
        message.info('报表生成中,请稍后~');
        deviceParams.forEach((i, r) => {
            let timeFrom = dateRange[r]?.dateFrom || moment().format(startFormat);
            let timeTo = dateRange[r]?.dateTo || moment().format(timeFormat);
            let fileName = `数据报表-${i.deviceType}-${i.deviceCode}-${moment(timeFrom).format(
                dateFormat,
            )}至${moment(timeTo).format(dateFormat)}`;
            let _quotas = i.sensors
                .split(',')
                .filter((item) => item !== '是否在线')
                .join(',');
            getExportDeviceHistoryUrl({
                deviceType: i.deviceType,
                deviceCode: i.deviceCode,
                quotas: _quotas,
                startTime: timeFrom,
                endTime: timeTo,
                fileName: fileName,
            })
                .then((res) => {
                    if (res && res.code === -1) return message.error(res.msg);
                    const url = `${window.location.origin}/PandaCore/GCK/FileHandleContoller/Download/name?name=${res.data}&_site=${globalConfig?.userInfo?.site}`;
                    const aDom = document.createElement('a');
                    aDom.href = url;
                    aDom.click();
                    aDom.remove();
                })
                .catch((err) => {
                });
        });
    };
    const exportFeatureBtn = () => {
        message.info('报表生成中,请稍后~');
        let _dataSource = tableData.sort((a, b) => {
            let _a = a.time;
            let _b = b.time;
            if (timeValue === 'contrast') {
                if (contrastOption === 'day') {
                    _a = `2000-01-01 ${a.time}:00`;
                    _b = `2000-01-01 ${b.time}:00`;
                }
                if (contrastOption === 'month') {
                    _a = `2000-01-${a.time}:00`;
                    _b = `2000-01-${b.time}:00`;
                }
            }
            return timeOrder === 'ascend' ? moment(_a) - moment(_b) : moment(_b) - moment(_a);
        });
        let _columns = [...columns];
        let timeFrom = dateRange?.[0]?.dateFrom || moment().format(startFormat);
        let timeTo = dateRange?.[0]?.dateTo || moment().format(timeFormat);
        let fileName = `特征数据-${moment(timeFrom).format(dateFormat)}至${moment(timeTo).format(
            dateFormat,
        )}`;
        let _dataIndex = [];
        let _titleWidth = [];
        let _title = _columns.map((item) => {
            _dataIndex.push(item.dataIndex);
            let _titleArr = [item.name, item.title];
            if (item.title.includes(item.name)) {
                _titleArr = [item.title];
            }
            let _titleStr = _titleArr.filter((item) => item).join('-');
            _titleWidth.push(_titleStr.length * 1);
            return _titleStr;
        });
        ExportExcel({
            name: fileName,
            content: [
                {
                    sheetData: _dataSource,
                    sheetFilter: _dataIndex,
                    sheetHeader: _title,
                    columnWidths: _titleWidth,
                },
            ],
        });
    };
    const handleTableData = useCallback(
        (data) => {
            // eslint-disable-next-line no-param-reassign
            // data = data.filter(item => item.sensorName !== '是否在线');
            const ignoreOutliers = checkboxData.find((item) => item.key === 'ignoreOutliers').checked;
            const dataIndexAccess = (dataItem, index) => {
                const {stationCode, sensorName} = dataItem;
                return `${stationCode}-${sensorName}-${index}`;
            };

            let format = timeFormat;
            if (timeValue === 'contrast') {
                format = contrastOption === 'day' ? '2020-01-01 HH:mm:00' : '2020-01-DD HH:mm:00';
            }
            // 判断是否是单设备,单设备则不显示设备名称
            // 处理表头数据
            const columnsData = data.map((item, index) => {
                const {stationCode, equipmentName, sensorName, unit, dataModel} = item;
                const dataIndex = dataIndexAccess(item, index);
                let _title = '';
                if (deviceConfig.current.oneDevice) {
                    _title = `${sensorName}${unit ? `(${unit})` : ''}`;
                } else {
                    _title = `${equipmentName}-${sensorName}${unit ? `(${unit})` : ''}`;
                }
                let col = {
                    title: _title,
                    dataIndex: dataIndex,
                    key: dataIndex,
                    ellipsis: true,
                    align: 'center',
                    width: 200,
                    name: equipmentName,
                };
                // 同期对比
                if (timeValue === 'contrast' && dataModel[0]) {
                    const time = item.dataModel[0]?.pt
                        ?.slice(0, contrastOption === 'day' ? 10 : 7)
                        ?.replace(/-/g, '');
                    col.title = `${equipmentName}-${sensorName}-${time}`;
                }
                return col;
            });

            // 格式化时间对齐数据, 生成行数
            const timeData = {};
            const buildDefaultData = (time) => {
                const obj = {key: time, time: time};
                data.forEach((item, index) => {
                    const dataIndex = dataIndexAccess(item, index);
                    obj[dataIndex] = '';
                    obj.name = item.equipmentName;
                });
                return obj;
            };
            data.forEach((item, index) => {
                const {stationCode, sensorName, dataModel} = item;
                dataModel &&
                dataModel.forEach((data) => {
                    const formatTime = moment(data.pt).format(format);

                    let time = formatTime;
                    if (timeValue === 'contrast') {
                        time = time.slice(contrastOption === 'day' ? 11 : 8, 16);
                    }

                    timeData[formatTime] = timeData[formatTime] || buildDefaultData(time);
                });
            });
            // 处理表格数据
            data.forEach((child, index) => {
                const {dataModel} = child;
                const dataIndex = dataIndexAccess(child, index);
                dataModel &&
                dataModel.forEach((value, j) => {
                    const formatTime = moment(value.pt).format(format);
                    const dataRow = timeData[formatTime];
                    if (dataRow) {
                        dataRow[dataIndex] = value.pv === null || value.pv === undefined ? '' : value.pv;
                    }
                });
            });
            const timeSort = (a, b) => {
                let aa = a,
                    bb = b;
                if (timeValue === 'contrast') {
                    aa = a.slice(contrastOption === 'day' ? 11 : 8, 16);
                    bb = b.slice(contrastOption === 'day' ? 11 : 8, 16);
                }
                return timeOrder === 'descend' ? -aa.localeCompare(bb) : aa.localeCompare(bb);
            };
            const times = Object.keys(timeData).sort(timeSort);
            const tableData = times.map((time) => timeData[time]);
            setColumns([timeColumn, ...columnsData]);
            setTableData(tableData);
        },
        [timeOrder, timeValue, contrastOption],
    );

    const [deviceAlarmSchemes, setDeviceAlarmSchemes] = useState([]);
    const beforChangeParams = (value = {}) => {
        // 不需要报警标线 或者 多曲线、多设备时不显示报警标线
        let _lengthEqual0 = deviceParams?.length === 0;
        let _lengthEqual1 = deviceParams?.length === 1;
        let _lengthMoreThan1 = deviceParams?.length > 1;
        let returnNothing = !needMarkLine || _lengthEqual0 || _lengthMoreThan1 || (_lengthEqual1 && deviceParams[0].sensors.split(',').length > 1)
        if (returnNothing) return Promise.resolve();
        return getDeviceAlarmScheme({
            data: deviceParams.map((item) => ({
                deviceType: item.deviceType,
                deviceCode: item.deviceCode,
                pointAddressID: item.pointAddressID,
                sensorName: item.sensors,
            })),
        })
            .then((res) => {
                if (res.code === 0) setDeviceAlarmSchemes(res.data || []);
                else setDeviceAlarmSchemes([]);
                return Promise.resolve();
            })
            .catch((err) => {
                setDeviceAlarmSchemes([]);
                return Promise.resolve();
            });
    };
    const handleDataThinKey = (diffYears, diffDays, diffHours, lineDataType) => {
        if (lineDataType === '原始曲线') {
            return {unit: '', zoom: ''};
        }
        // edit by zy 根据选择的时长控制抽稀频度
        if (diffYears > 0) {
            if (diffYears === 1) return {unit: 'h', zoom: '24'};
            return {unit: 'h', zoom: '48'};
        } else if (diffYears === 0 && diffDays > 0) {
            if (diffDays > 90) return {unit: 'h', zoom: '24'};
            if (diffDays > 30) return {unit: 'h', zoom: '4'};
            if (diffDays > 15) return {unit: 'h', zoom: '2'};
            if (diffDays > 7) return {unit: 'h', zoom: '1'};
            if (diffDays > 3) return {unit: 'min', zoom: '20'};
            if (diffDays > 1) return {unit: 'min', zoom: '15'};
            if (diffDays === 1) return {unit: 'min', zoom: '5'};
        } else if (diffYears === 0 && diffDays === 0 && diffHours > 0) {
            if (diffHours > 12) return {unit: 'min', zoom: '5'};
            if (diffHours > 4) return {unit: 'min', zoom: '1'};
            if (diffHours > 1) return {unit: 's', zoom: '30'};
            if (diffHours > 0) return {unit: 's', zoom: '5'};
            return {unit: 's', zoom: '5'};
        } else {
            return {unit: '', zoom: ''};
        }
    };

    // 处理接口服务参数的变化
    const onChangeParams = (value = {}) => {
        const {dateRange, isDilute, ignoreOutliers, zoom, unit} = value;
        let _diffDays = moment(dateRange[0].dateTo).diff(dateRange[0].dateFrom, 'days');
        // 查询时段大于7天时,不提供1分钟的抽稀选项。
        if (_diffDays > 7 && zoom === '1' && unit === 'min') {
            return false;
        }
        const requestArr = [];
        const acrossTables = [];
        const zoomArray = [];
        // 这部分功能有问题,等待解决后上线 2024年3月13日
        let hasDiscreteDeviceType = false;
        deviceParams
            .map((item) => {
                let _item = {...item};
                _item.sensors = item.sensors;
                // special 业务
                if (special1) {
                    _item.sensors += `,${special1.name}`;
                }
                return _item;
            })
            .forEach((i) => {
                if (i.sensors && i.deviceCode)
                    acrossTables.push(_.omit(i, ['pointAddressID']));
                // 这部分功能有问题,等待解决后上线 2024年3月13日
                if (discreteDeviceType.includes(i.deviceType)) {
                    hasDiscreteDeviceType = true;
                }
            });
        if (!acrossTables?.length || !dateRange.length) {
            handleTableData([]);
            setChartDataSource([]);
            return;
        }
        dateRange.forEach((item) => {
            const param = {
                isDilute,
                zoom,
                unit,
                ignoreOutliers,
                dateFrom: item.dateFrom,
                dateTo: item.dateTo,
                acrossTables,
                isBoxPlots: isBoxPlots,
            };
            let diffYears = moment(item.dateTo).diff(moment(item.dateFrom), 'years');
            let diffDays = moment(item.dateTo).diff(moment(item.dateFrom), 'days');
            let diffHours = moment(item.dateTo).diff(moment(item.dateFrom), 'hours');
            let zoomParam =
                activeTabKey === 'curve'
                    ? handleDataThinKey(diffYears, diffDays, diffHours, lineDataType)
                    : !isDilute
                        ? {zoom: '', unit: ''}
                        : {}; // 表格也支持全数据模式;
            let _finalParams = {...param, ...zoomParam};
            // 2024年1月8日 抽稀间隔大于等于12小时时,会存在线性插值导致抽稀间隔内数据条数大于预期的问题。需要增加一个额外参数处理该情况。
            if (_finalParams.zoom) {
                let _num = Number(_finalParams.zoom);
                let _isNaN = isNaN(_num);
                if (!_isNaN && _num >= 12) _finalParams.isInterpolation = false;
            }
            // 2024年1月23日 增加预测曲线,单设备单曲线
            // 同期对比不允许、多设备的不允许预测
            if (dateRange.length === 1 && predicateDevice) {
                _finalParams.acrossTables.push(predicateDevice);
            }
            // 2024年3月11日 如果设备是某些特殊设备,则采用离散型算法
            // 这部分功能有问题,等待解决后上线 2024年3月13日
            if (hasDiscreteDeviceType && ignoreOutliers) {
                _finalParams.algorithmName = "derivative";
            }
            requestArr.push(getHistoryInfo(_finalParams));
        });
        setLoading(true);
        Promise.all(requestArr)
            .then((results) => {
                setLoading(false);
                emptyOrError.current.error = false;
                if (results.length) {
                    let data = [];
                    // let _predicateData = [];
                    results.forEach((res, index) => {
                        const {dateFrom, dateTo} = dateRange?.[index] ?? {};
                        if (res.code === 0 && res.data.length) {
                            res.data.forEach((d) => {
                                d.dateFrom = dateFrom || '';
                                d.dateTo = dateTo || '';
                                /**
                                 * @date: 2023年10月25日
                                 * @description: 数据连续补点之后,首值、尾值、最大值、最小值不会补,都为null。
                                 *     为保证显示,将补点之后的数据的首值、尾值、最大值、最小值同时为null的情况变更为点的值。
                                 *
                                 *     请注意,此项为重要变更,此变更会影响原始数据。
                                 */
                                // d.dataModel=[];
                                d.dataModel = d.dataModel.map((item) => {
                                    let {firstPV, lastPV, maxPV, minPV, pv} = item;
                                    if (pv !== null && firstPV === null && lastPV === null && maxPV === null && minPV === null) {
                                        firstPV = pv;
                                        lastPV = pv;
                                        maxPV = pv;
                                        minPV = pv;
                                    }
                                    return {
                                        ...item,
                                        firstPV,
                                        lastPV,
                                        maxPV,
                                        minPV,
                                    };
                                });
                            });
                            // 加入预测
                            (predicateDevice ? deviceParams.concat(predicateDevice) : deviceParams).forEach((p) => {
                                // 返回数据按查询指标顺序排序
                                const sensors = p.sensors?.split(',') ?? [];
                                if (sensors?.length) {
                                    sensors.push('是否在线');
                                    if (special1) {
                                        sensors.push(special1.name);
                                    }
                                }
                                const list = sensors.map((s) => {
                                    const dataItem = res.data.find(
                                        (d) => d.stationCode === p.deviceCode && d.sensorName === s,
                                    );
                                    if (dataItem) {
                                        dataItem.dateFrom = dateFrom || '';
                                        dataItem.dateTo = dateTo || '';
                                        dataItem.deviceType = p.deviceType;
                                        return dataItem;
                                    } else {
                                        return {};
                                    }
                                }).filter((item) => item.sensorName);
                                // 预测的
                                data = data.concat(list);
                                // _predicateData = _predicateData.concat(list.filter(item => item.deviceType === '预测'));
                            });
                        }
                    });
                    setLoading(false);
                    if (data.length !== 0) {
                        emptyOrError.current.empty = false;
                    } else {
                        data = handleFakeData(dateRange, deviceParams) ?? []
                    }
                    handleTableData(data)
                    setChartDataSource(data);
                    // setPredicateData(_predicateData);
                }
            })
            .catch((err) => {
                let data = handleFakeData(dateRange, deviceParams) ?? [];
                handleTableData(data);
                setChartDataSource(data);
                message.info('未查询到数据,请重试~');
                setLoading(false);
            });
    };

    useEffect(() => {
        if (!completeInit) return;
        const {dataThin, ignoreOutliers, zoom, unit} = dataConfig;
        beforChangeParams().finally(() => {
            onChangeParams({
                isDilute: dataThin,
                ignoreOutliers,
                zoom,
                unit,
                dateRange,
                isBoxPlots: isBoxPlots,
            });
        });
    }, [dateRange, dataConfig, deviceParams, chartType, lineDataType, completeInit, algorithmValue]);
    const handleChange = (pagination, filter, sort) => {
        if (sort.field === 'time') {
            setTimeOrder(sort.order);
        }
    };
    const tableMemo = useMemo(() => {
        return (
            <>
                <div className={`${prefixCls}-options`}>
                    {renderTimeOption}
                    {renderCurveOption()}
                </div>
                <div className={`${prefixCls}-content`} ref={tableRef}>
                    {chartDataSource.length > 0 ? (
                        // <BasicTable
                        <VirtualTable
                            className={`${prefixCls}-virtual-table`}
                            theme={theme}
                            dataSource={tableData.sort((a, b) => {
                                let _a = a.time;
                                let _b = b.time;
                                if (timeValue === 'contrast') {
                                    if (contrastOption === 'day') {
                                        _a = `2000-01-01 ${a.time}:00`;
                                        _b = `2000-01-01 ${b.time}:00`;
                                    }
                                    if (contrastOption === 'month') {
                                        _a = `2000-01-${a.time}:00`;
                                        _b = `2000-01-${b.time}:00`;
                                    }
                                }
                                return timeOrder === 'ascend' ? moment(_a) - moment(_b) : moment(_b) - moment(_a);
                            })}
                            columns={columns}
                            tableProps={tableProps}
                            pagination={false}
                            onChange={handleChange}
                            // scroll={{ x: 'max-content', y: 'calc(100% - 40px)' }}
                            scroll={{
                                x: 'max-content',
                                y: tableRef.current ? tableRef.current.getBoundingClientRect().height - 40 : 0,
                            }}
                        />
                    ) : (
                        <PandaEmpty/>
                    )}
                </div>
            </>
        );
    }, [
        timeOrder,
        chartDataSource,
        columns,
        tableProps,
        tableData,
        isSingleStatusSensor,
        dateRange,
        tableRef.current,
    ]);
    const returnLongestPeriod = (data) => {
        let _earliest = '';
        let _latest = '';
        data.forEach((item) => {
            let _length = item.dataModel.length;
            let _tempFirst = item.dataModel[0].pt;
            let _tempLast = item.dataModel[_length - 1].pt;
            if (_earliest) {
                _earliest = moment(_earliest) > moment(_tempFirst) ? _tempFirst : _earliest;
            } else {
                _earliest = _tempFirst;
            }
            if (_latest) {
                _latest = moment(_latest) < moment(_tempLast) ? _tempLast : _latest;
            } else {
                _latest = _tempLast;
            }
        });
        return `${_earliest} - ${_latest}`;
    };
    const renderPanel = (model) => {
        if (model === 'curve') {
            return (
                <>
                    <div className={`${prefixCls}-options`}>
                        {renderTimeOption}
                        {renderCurveOption(
                            true,
                            deviceParams?.length === 1 && deviceParams?.[0]?.sensors?.split(',').length === 1,
                            isSingleStatusSensor,
                        )}
                    </div>
                    {lineDataType === '原始曲线' && false ? (
                        <div style={{marginTop: 10}}>展示区间:{returnLongestPeriod(chartDataSource)}</div>
                    ) : (
                        ''
                    )}
                    <div className={`${prefixCls}-content`}>
                        {grid === true ? (
                            <GridChart
                                emptyOrError={emptyOrError.current}
                                curveCenter={curveCenter}
                                prefixCls={prefixCls}
                                dataSource={chartDataSource}
                                contrast={timeValue === 'contrast'}
                                contrastOption={contrastOption}
                                deviceAlarmSchemes={deviceAlarmSchemes}
                                dateRange={dateRange}
                                allPointAddress={allPointAddress}
                                allSensorType={allSensorType}
                                loading={loading}
                                setLoading={setLoading}
                            />
                        ) : (
                            <SingleChart
                                emptyOrError={emptyOrError.current}
                                dateRange={dateRange}
                                showBoxOption={showBoxOption}
                                lineDataType={lineDataType}
                                curveCenter={curveCenter}
                                showGridLine={chartGrid}
                                prefixCls={prefixCls}
                                dataSource={chartDataSource}
                                predicateData={predicateData}
                                chartType={isBoxPlots ? chartType : null}
                                contrast={timeValue === 'contrast'}
                                contrastOption={contrastOption}
                                deviceAlarmSchemes={deviceAlarmSchemes}
                                theme={theme}
                                special={{
                                    special1, // 频率业务
                                    allPointAddress,
                                    allSensorType, // 后续新增的开关量的特殊业务,用来处理开关量业务
                                }}
                            />
                        )}
                    </div>
                </>
            );
        }
        if (model === 'table') {
            return tableMemo;
        }
    };
    // 获取字段配置
    const getDefaultOptions = async () => {
        // 特定设备
        // 这部分功能有问题,等待解决后上线 2024年3月13日
        getDictionaryInfoAll({
            level: '离散算法设备类型',
        }).then(res => {
            if (res.code === 0 && res.data.length) {
                let deviceType = res.data.find(item => item.fieldName === '设备类型')?.fieldValue;
                setDiscreteDeviceType(deviceType.split(',').filter(item => item))
            }
        })

        // 非单曲线、单指标不执行
        if (
            deviceParams?.length !== 1 ||
            (deviceParams?.length === 1 && deviceParams?.[0]?.sensors?.split(',')?.length > 1)
        )
            return setCompleteInit(true);
        setLoading(true);
        const {deviceCode, deviceType, sensors} = deviceParams[0];
        let _id = (
            await getPointAddress({
                code: deviceCode,
            })
        )?.data?.[0]?.id;
        let _params = {};
        if (_id) _params.versionId = _id;
        // 多曲线的居中,容易导致曲线被截断,故多曲线时,不请求
        let _request0 = getDictionaryInfoAll({
            level: '组件_ec_historyview',
        });
        // 以下请求为处理状态值、开关值的图表,只允许单曲线单指标情况下展示
        let _request1 = getPointAddressEntry(_params);
        let _request2 = getSensorType();
        // let _request3 = getPredicateSensor({deviceCode, sensors});
        await Promise.all([_request0, _request1, _request2]).then((result) => {
            if (result) {
                let _res0 = result[0];
                let _res1 = result[1];
                let _res2 = result[2];
                // let _res3 = result[3];
                let _checkboxData = [...checkboxData];
                // 单设备单曲线时,查询是否配置为预测点
                /*                if (_res3.code === 0 && _res3.data) {
                                    // 1. 如果是单曲线,并且配置了预测,那么默认开启预测;
                //                    2024年3月11日 物联预测功能支撑后,再开发这部分
                                                        _checkboxData.push({
                                                            key: 'predicate',
                                                            label: '数据预测',
                                                            checked: true,
                                                            showInCurve: true,
                                                            showInTable: true,
                                                        })
                                    setPredicateDevice({..._res3.data, deviceType: '预测'});
                                } else {
                                    setPredicateDevice(null);
                                }*/
                // 查字典配置
                if (_res0.code === 0) {
                    let _opt = _res0.data.reduce((final, cur) => {
                        final[cur.fieldName] = cur.fieldValue;
                        return final;
                    }, {});
                    _checkboxData = _checkboxData.map((item) => {
                        let _item = {...item};
                        if (_opt[item.label] !== undefined) {
                            _item.checked = _opt[item.label] === 'true';
                        }
                        return _item;
                    });
                    setCheckboxData(_checkboxData);
                }
                // 查点表配置
                if (_res1.code === 0) {
                    let _sensorConfig = _res1.data.find((item) => item?.name.trim() === sensors.trim());
                    let _statusName = _sensorConfig?.statusName;
                    setAllPointAddress(_res1.data);
                    if (_statusName) {
                        let _statusConfig = _res1.data.find((item) => item?.name.trim() === _statusName.trim());
                        let _valDesc = _statusConfig?.valDesc || '';
                        setSpecial1({
                            name: _statusName,
                            valDesc: _valDesc.split(';').reduce((final, cur) => {
                                let _arr = cur.split(':');
                                final[_arr[0]] = _arr[1];
                                return final;
                            }, {}),
                        });
                    }
                }
                // 标记sensor是什么类型的
                if (_res2.code === 0) {
                    setAllSensorType(_res2.data);
                    let _sensorID = _res1.data?.find((item) => item.name === sensors)?.sensorTypeID;
                    let _sensor = _res2.data?.find((item) => item.id === _sensorID)?.type;
                    let _isStatusSensor = ['状态值', '开关值'].includes(_sensor);
                    setIsSingleStatusSensor(_isStatusSensor);
                }
            }
        });
        setCompleteInit(true);
    };
    useEffect(() => {
        getDefaultOptions();
    }, [deviceParams]);
    let percentTimer = useRef({
        timer: null,
    });
    //  加载动画
    useEffect(() => {
        if (loading === null) return;
        if (loading) {
            let _percent = percent;
            percentTimer.current.timer = setInterval(() => {
                _percent += 5;
                if (_percent > 95) return clearInterval(percentTimer.current.timer);
                setPercent(_percent);
            }, 100);
        } else {
            clearInterval(percentTimer.current.timer);
            setPercent(100);
            setTimeout(
                () => {
                    setPercent(0);
                },
                lineDataType === '原始曲线' ? 500 : 0,
            );
        }
    }, [loading]);
    return (
        <div
            className={classNames(prefixCls, theme === 'BI' ? BIStyles.historyViewComponents : '', 'wkt-scroll-light')}
            style={{background: theme === 'BI' ? '#282b34' : '#ffffff'}}>
            <div className={classNames(`${prefixCls}-spin`)} style={{position: 'relative'}}>
                {loading || percent !== 0 ? (
                    <div className={classNames(`${prefixCls}-progressWrapper`)}>
                        {lineDataType === '原始曲线' ||
                        (lineDataType === '特征曲线' &&
                            moment(dateRange?.[0]?.dateTo).diff(moment(dateRange?.[0]?.dateFrom), 'days') >=
                            30) ?
                            <div className={classNames(`${prefixCls}-contentWrapper`)}>
                                <Progress
                                    percent={percent}
                                    steps={20}
                                    className={classNames(`${prefixCls}-progress`, `${prefixCls}-blink-2`)}
                                    showInfo={false}
                                />
                                <div className={classNames(`${prefixCls}-tip`)}>加载中...</div>
                            </div> :
                            <Spin spinning={loading || false} tip={'数据加载中...'} delay={1000}
                                  style={{background: 'transparent'}}/>
                        }
                    </div>
                ) : (
                    ''
                )}
                {showModels.length === 1 && (
                    <div className={`${prefixCls}-single-panel`}>{renderPanel(showModels[0])}</div>
                )}
                {showModels.length > 1 && (
                    <Tabs
                        activeKey={activeTabKey}
                        onChange={(key) => setActiveTabKey(key)}
                        centered
                        tabBarExtraContent={{
                            left: <h3>{title}</h3>,
                            right: (
                                <div className={`${prefixCls}-extra-right`}>
                                    {activeTabKey === 'table' && (
                                        <>
                                            <Button type="link" onClick={exportFeatureBtn}>
                                                <DownloadOutlined/>
                                                下载
                                            </Button>
                                        </>
                                    )}
                                </div>
                            ),
                        }}
                    >
                        <Tabs.TabPane key="curve" tab="曲线" forceRender={true}>
                            {activeTabKey === 'curve' ? renderPanel('curve') : ''}
                        </Tabs.TabPane>
                        <Tabs.TabPane key="table" tab="表格">
                            {renderPanel('table')}
                        </Tabs.TabPane>
                    </Tabs>
                )}
            </div>
        </div>
    )
};

HistoryView.propTypes = {
    grid: PropTypes.bool,
    title: PropTypes.string,
    defaultChecked: PropTypes.oneOf(['twelveHours', 'roundClock', 'oneWeek', 'oneMonth']),
    tableProps: PropTypes.object,
    deviceParams: PropTypes.arrayOf(
        PropTypes.objectOf({
            deviceCode: PropTypes.string,
            sensors: PropTypes.string,
            deviceType: PropTypes.string,
            pointAddressID: PropTypes.number, // 可选,配置了将会查询相关报警方案配置
        }),
    ),
    defaultModel: PropTypes.oneOf(['curve', 'table']),
    showModels: PropTypes.arrayOf(PropTypes.oneOf(['curve', 'table'])),
    defaultDate: PropTypes.string,
    BIMode: PropTypes.bool
};

HistoryView.defaultProps = {
    grid: false,
    title: '指标曲线',
    defaultChecked: 'roundClock',
    tableProps: {},
    defaultModel: 'curve',
    showModels: ['curve', 'table'],
    needMarkLine: true,
    defaultDate: 'day',
    BIMode: false
};

export default HistoryView;