/**
 * * 轻量化报表通用配置页面 * create by ChenLong on 2022/6/22 *
 * 功能路径:src\pages\product\ReportsManage\ReportsManage.js * 菜单参数列表:*变量名*(变量说明,数据类型,是否必填,取值范围)
 *
 * @changelog:
 *  editComponentVisible && detailsComponentVisible  共同作用组件的显示
 */
/**
 * @description: 功能描述:参考台账概念,重新定义
 * @tips: 1. 如果需要对字段进行处理,增加功能之类的。需要提前确定返回值的类型.
 *         2. 如果要用customerState来控制页面按钮等,需要按照给定的权限值进行配置
 * @params: <ReportManage
 *     params={{reportName,pageSize,filterFields,filterValues,state,customerState}}>
 *
 *
 *
 *     reportName: 报表名称;
 *           pageSize: 按需配置,默认加载100;
 *
 *
 *
 *     ***************filterFields/filterValues多用于以组件的形式嵌入,将需要过滤的条件传入********************
 *
 *
 *
 *     filterFields: 需要默认加载的过滤条件的field,用|分割,与filterValues一一对应;
 *           filterValues:
 *
 *
 *     需要默认加载的过滤条件的value,用|分割,与filterFields一一对应;当某个字段的filterValues为多个时,控件必须配置成多选才可生效;
 *
 *
 *
 *     *************************************************************************************************
 *
 *
 *
 *                    state: delete|edit|scan 各种权限;
 *           customerState:
 *
 *
 *     ['filters','sortBtn','exportBtn','editBtn','deleteBtn','pagination'];
 *
 *     sortFields:
 *
 *        '排序字段1,排序字段2,排序字段3'
 *
 *
 *
 *     ---------------------------------------权限过滤-----------------------------------------
 *
 *
 *
 *     permissionType: 部门|站点|用户
 *           permissionField: 【字段名】
 *
 *
 *
 *     ---------------------------------------------------------------------------------------
 * @config:
 *  【数值】 [prefix]_d%|0.00|_d%[suffix]|金额 = 前缀|精度|后缀|金额类的数据(千分位),可分别设置。
 *  【标签】 split=,
 *
 *     分隔符。
 *
 *     【功能】 功能配置框内,配置需要跳转功能所需参数,type、url是必须功能,需要type判断类型,需要通过url去解析加载组件。
 * @type:
 *  【文本】普通文本
 *  【数值】数值类型的文本
 *  【标签】文本渲染成标签,具有不同颜色;
 *  【功能】“功能”会在当前页内去展示,会卸载掉列表页,加载功能组件。配置 type +
 *
 *
 *          url + 自定义字段 的配置项,自行解析加载即可;
 *   -------------------- 待需求提出后开发 -----------------
 *
 *
 *
 *     【链接】内链外链,点击可跳转;配置规则:配置链接即可;
 *  【弹窗】modal弹窗弹出,弹窗内的具体业务自行配置;配置规则:[function_name];[...params];
 *
 *
 *
 *          ------------------------------------------------------
 *  【附件】
 * @table:
 *  表头:表头需要支持多级表头、合并;
 *  列:列支持设置筛选;
 *  固定行、固定列:可根据配置生成固定行、列;
 * @control:
 *  固定筛选:拥有固定筛选框,根据配置显示可搜索字段;
 *
 *
 *
 *     可配置筛选框:根据字段配置,将字段设置成筛选条件,枚举出该字段所有值,提供用户进行选择,然后进行筛选;筛选框具体形态可根据配置字段来渲染;
 *  导出功能:各类导出功能按钮;
 *
 *
 *
 *     时间筛选框:单表唯一;需要变更,支持多时间参数的筛选
 * @state: 参考台账权限 delete 全部权限
 *  edit   除删除外的权限
 *  scan   查看权限
 */
import React, { useState, useEffect, useRef } from 'react';
import {
  Row,
  Button,
  Tag,
  message,
  Form,
  Space,
  Modal,
  Select,
  Table,
  Dropdown,
  Menu,
  Spin,
  Popconfirm,
  Tooltip,
} from 'antd';
import {
  SortAscendingOutlined,
  MinusCircleOutlined,
  ExportOutlined,
  FormOutlined,
  PlusOutlined,
  DeleteOutlined,
  QuestionCircleOutlined,
  HeartTwoTone,
  HeartOutlined,
  DownOutlined,
} from '@ant-design/icons';
import BasicTable from '@wisdom-components/basictable';
import ReturnControlComponent from './Components/Control';
import { reportService } from '../api/index';
import style from './ReportsManage.less';
import { exportAccountData } from '../api/service/report';
import extraComponents from './extra/extraComponents';
import DatePickerGroup from '../components/DatePickerGroup';
import moment from 'moment';
import DetailsComponent from './extra/detailsComponent';
import {
  handleNumber,
  handleTag,
  handleText,
  handleLink,
  handleWidget,
  handleModal,
  handleDateString,
  handleDateTimeString,
  handlePageSize,
  handleSortFields,
  handleNumberTag,
} from './utils/handlers';
import { hasMoney, isArray, isNumber, isString, returnHandledNumber } from './utils/utils';
import { connect } from 'react-redux';
import ReportEditForm from './ReportEditForm';
import { exportJPG } from '../api/service/report';

const ControlsType = ['下拉', '多选', '日期'];
const fieldSplitStr = '-'; // fieldGroup用来分割
const { Option } = Select;
const dateFormat = 'YYYY-MM-DD'; // 日期格式化
const initDateModel = 'all';
let timer = null;
const PERMISSION = {
  delete: [
    'addBtn',
    'filters',
    'pagination',
    // 操作条按钮
    'sortBtn',
    'exportBtn',
    // 操作列
    'editBtn',
    'deleteBtn',
  ],
  edit: [
    'addBtn',
    'filters',
    'pagination',
    'sortBtn',
    'exportBtn',
    // 操作列
    'editBtn',
  ],
  scan: ['filters', 'pagination', 'sortBtn'],
};
const USER_ID = window.globalConfig.userInfo.OID;
const MODEL = ['all', 'year', 'quarter', 'month', 'week', 'day'];
const ReportsManage = (props) => {
  const {
    reportName,
    pageSize,
    filterFields,
    filterValues,
    state,
    customState,
    sortFields,
    permissionType,
    permissionField,
  } = props.params;

  const handleCustomerState = (customState) => {
    if (isArray(customState)) {
      return customState;
    } else if (isString(customState)) {
      return customState.split(',');
    }
  };

  const permission = customState ? handleCustomerState(customState) : PERMISSION[state || 'delete'];

  const tableWrapperRef = useRef();
  const controlRef = useRef();
  if (!reportName)
    return (
      <div className={style.lackParams}>未配置reportName,请完善配置并重新登陆后查看页面!</div>
    );
  const [isInit, setIsInit] = useState(true);
  const [firstToGetData, setFirstToGetData] = useState(false);
  const [tableStruct, setTableStruct] = useState([]); // 临时使用,看后续是否需要保留
  const [columns, setColumns] = useState([]); // 表头设置
  const [tableData, setTableData] = useState([]); // 表数据
  const [reportConfigs, setReportConfigs] = useState([]); // 表设置
  const [pagination, setPagination] = useState({
    current: 1,
    total: 0,
    pageSize: handlePageSize(pageSize) || 100,
    pageSizeOptions: [...new Set([20, 50, 100].concat(handlePageSize(pageSize)))]
      .filter((item) => Number(item))
      .sort((a, b) => Number(a) - Number(b)),
    showQuickJumper: true,
    showSizeChanger: true,
    onShowSizeChange: (current, size) => {
      let _pagination = { ...pagination };
      _pagination.current = current;
      _pagination.pageSize = size;
      setPagination(_pagination);
      getData(_pagination);
    },
    onChange: (current, size) => {
      let _pagination = { ...pagination };
      _pagination.current = current;
      _pagination.pageSize = size;
      setPagination(_pagination);
      getData(_pagination);
    },
  });
  const [controls, setControls] = useState([]); // 用来存储操作控件
  const [searchContent, setSearchContent] = useState(''); // 搜索框内的值
  const [searchPlaceholder, setSearchPlaceholder] = useState([]); // 搜索框的placeholder
  const [filterObject, setFilterObject] = useState({}); // 存控制条中,选了筛选条件的值
  const [modalVisible, setModalVisible] = useState(false);
  const [allSortFields, setAllSortFields] = useState([]); // 设置所有列表
  const [selectedSortFields, setSelectedSortFields] = useState([
    {
      label: '主要排序',
      value: '',
      sort: 'asc',
    },
  ]);
  const [summaryArray, setSummaryArray] = useState([]); // 总结栏,包括小计、总计
  const [tableY, setTableY] = useState(500);
  const [tableX, setTableX] = useState(1820);
  const [listHeight, setListHeight] = useState(0);
  const [tableHeaderLevel, setTableHeaderLevel] = useState(null);
  const [exportLoading, setExportLoading] = useState(false);
  const [extraModal, setExtraModal] = useState(false);
  const [hasTotal, setHasTotal] = useState(false);
  const [hasSinglePage, setHasSinglePage] = useState(false);
  const [tableLoading, setTableLoading] = useState(false);
  const [mergeObject, setMergeObject] = useState({});
  // const
  const [timeFrom, setTimeFrom] = useState(moment().startOf(initDateModel).format(dateFormat));
  const [timeTo, setTimeTo] = useState(moment().endOf(initDateModel).format(dateFormat));
  const [extra, setExtra] = useState(<></>);
  const [sortModalVisible, setSortModalVisible] = useState(false);
  const [currentReportId, setCurrentReportId] = useState(null);
  const [hasDatePicker, setHasDatePicker] = useState('');
  const [defaultDateConfig, setDefaultDateConfig] = useState({
    defaultModel: 'year',
    defaultDate: null,
  });
  const [dateModel, setDateMode] = useState('all');

  const [detailsComponentVisible, setDetailsComponentVisible] = useState(false); // 是否显示详情组件
  const [modalType, setModalType] = useState('');
  const [currentData, setCurrentData] = useState({}); // 设置当前编辑数据
  const [sorterObject, setSorterObject] = useState({});
  const [detailConfig, setDetailConfig] = useState({ url: '', type: '', params: {} });
  const [controlsHeight, setControlsHeight] = useState(44);
  const [getNewData, setGetNewData] = useState(false);
  const [isLocalDataSource, setIsLocalDataSource] = useState(0); // 如果是本地数据源,那么值为0;反之,则是外部数据源
  const menu = () => {
    const _item = [
      {
        label: (
          <Button
            size="middle"
            loading={exportLoading}
            type="text"
            onClick={() => exportModule('pdf', 'pdf')}
            icon={<ExportOutlined />}
          >
            导出pdf
          </Button>
        ),
        key: 'exportPdf',
      },
      {
        label: (
          <Button
            size="middle"
            loading={exportLoading}
            type="text"
            onClick={() => exportModule('excel', 'xls')}
            icon={<ExportOutlined />}
          >
            导出Excel
          </Button>
        ),
        key: 'exportExcel',
      },
      {
        label: (
          <Button
            size="middle"
            loading={exportLoading}
            type="text"
            onClick={() => exportImage()}
            icon={<ExportOutlined />}
          >
            导出JPG
          </Button>
        ),
        key: 'excelPdf',
      },
    ];
    return <Menu items={_item} />;
  };
  const exportModule = (type, extension) => {
    setExportLoading(true);
    let _data = addFilterAndSearchParams({
      reportName,
      pageIndex: 0,
      pageSize: 0,
      userId: USER_ID,
    });
    exportAccountData({ responseType: 'blob' }, { exportType: type }, _data)
      .then((res) => {
        if (res && res.code === -1) return message.error(res.msg);
        const url = window.URL.createObjectURL(
          new Blob([res], { type: 'application/octet-stream;charset=UTF-8' }),
        );
        const a = document.createElement('a');
        a.href = url;
        a.target = '_blank';
        a.download =
          `${reportName}${moment().format('YYYY-MM-DD-HH-mm-ss').replaceAll('-', '')}.` + extension;
        a.click();
        a.remove();
        setExportLoading(false);
      })
      .catch((err) => {
        setExportLoading(false);
      });
  };
  const exportImage = () => {
    let _data = addFilterAndSearchParams({
      reportName,
      pageIndex: 0,
      pageSize: 0,
      userId: USER_ID,
    });
    exportJPG({ responseType: 'blob' }, _data).then((res) => {
      if (res && res.code === -1) return message.error(res.msg);
      const url = window.URL.createObjectURL(
        new Blob([res], { type: 'application/zip;charset=UTF-8' }),
      );
      const a = document.createElement('a');
      a.href = url;
      a.target = '_blank';
      a.download = `${reportName}${moment().format('YYYY-MM-DD-HH-mm-ss').replaceAll('-', '')}.zip`;
      a.click();
      a.remove();
      setExportLoading(false);
    });
  };
  const searchData = (e) => {
    getData(pagination);
  };
  const controlSelectChange = (fieldAlias, e) => {
    let _filterArray = { ...filterObject };
    _filterArray[fieldAlias] = e;
    setFilterObject(_filterArray);
  };
  const searchInputChange = (e) => {
    setSearchContent(e.target.value);
  };
  const setConfig = (config) => {
    getControlsBarConfig(config);
    getTableLevel(config);
  };
  const addFilterAndSearchParams = (data) => {
    let _data = { ...data };
    // 搜索框是否有值
    if (searchContent) _data.content = searchContent;
    // filterObject是存起来的控制栏的过滤条件
    let _filters = Object.keys(filterObject)
      .filter((key) => {
        let _value = filterObject[key];
        return (isString(_value) && _value) || (isArray(_value) && _value.length);
      })
      .map((key) => {
        let _value = filterObject[key];
        if (isString(_value) && _value)
          return {
            fieldAlias: key,
            fieldValue: _value,
          };
        if (isArray(_value) && _value.length)
          return {
            fieldAlias: key,
            fieldValue: _value.join(','),
          };
        return false;
      });
    // 加上时间过滤参数
    if (dateModel !== 'all' && hasDatePicker && timeFrom && timeTo) {
      _filters.push({
        fieldAlias: hasDatePicker,
        fieldValue: `${timeFrom} 00:00:00,${timeTo} 23:59:59`,
      });
    }
    // 合并手动传入的filters;当配置为筛选框时,筛选框选择值后,会优先取筛选框值
    if (filterFields && !_filters.find((item) => item.fieldAlias === filterFields)) {
      let _customerFilterArray = filterFields.split('|');
      let _customerValueArray = filterValues.split('|');
      _customerFilterArray.forEach((item, index) => {
        _filters.push({
          fieldAlias: item,
          fieldValue: _customerValueArray[index] || '',
        });
      });
    }
    // 表格上的自定义排序的按钮
    if (sorterObject && sorterObject.order) {
      _data.sortFields = `${sorterObject.columnKey} ${
        sorterObject.order === 'ascend' ? 'asc' : 'desc'
      }`;
    }
    // 增加权限过滤的参数
    if (permissionType && permissionField) {
      _data.filterType = permissionType;
      _data.filterField = permissionField;
    }
    // 并入 _data
    if (_filters.length) _data.filters = _filters;
    return _data;
  };
  // 排序字符串处理成数组
  const handleSortString = (sortString) => {
    // selectedSortFields
    let _sortStringArray = sortString.split(',').map((item, index) => {
      let _item = item.split(' ');
      if (index === 0) {
        return {
          label: '主要排序',
          value: _item[0].replace(/\[|\]/g, ''),
          sort: _item[1],
        };
      } else {
        return {
          label: '次要排序',
          value: _item[0].replace(/\[|\]/g, ''),
          sort: _item[1],
        };
      }
    });
    setSelectedSortFields(_sortStringArray);
  };
  /** @description: 根据是否向下合并处理数据,返回合并的key的数组 */
  const returnMergeArray = (config) => {
    return config.filter((item) => item.isMerge).map((item) => item.fieldAlias);
  };
  /** @description: 根据配置和数据,计算出该合并的字段和每一行是否合并 */
  const handleDataToGetRowSpanArray = (config, data) => {
    let _arr = returnMergeArray(config);
    let _merge = {};
    // _merge:{爱好:[[0,3],[3,5]]}
    _arr.forEach((key) => {
      _merge[key] = {};
      let _currentIndex = 0;
      data.forEach((item, index) => {
        if (index > 0) {
          if (item[key] === data[index - 1][key]) {
            _merge[key][_currentIndex] += 1;
            _merge[key][index] = 0;
          } else {
            _currentIndex = index;
            _merge[key][index] = 1;
          }
        } else {
          _merge[key][0] = 1;
        }
      });
    });
    return _merge;
  };
  const handleData = () => {};
  const getData = (pagination) => {
    setTableLoading(true);
    const { pageSize, current } = pagination;
    // 搜索条件附加到params
    let _data = addFilterAndSearchParams({
      reportName: reportName,
      pageIndex: current,
      pageSize: pageSize,
      userId: USER_ID,
    });
    // sortFields
    reportService
      .getReportInfo(_data)
      .then((res) => {
        if (res.code === 0) {
          let _reportDetails = res.data?.reportDetails;
          let _statisticalValues = res.data?.statisticalValues;
          // webAPIData 存在值时使用webAPIData,否则使用原始数据
          let _tableData = res.data.webAPIData?.webAPIData
            ? JSON.parse(res.data.webAPIData.webAPIData)
            : res.data?.data?.list.map((item) => {
                if (Object.prototype.toString.call(item) === '[object String]') {
                  return JSON.parse(item);
                }
                return item;
              }) || [];
          let _sortString = res.data.sortString;
          if (isInit) {
            setIsInit(false);
          }
          setIsLocalDataSource(res.data.sourcesId);
          getTableSummaryConfig(_reportDetails, _statisticalValues);
          getTableHeaderConfig(_reportDetails, _tableData);
          let _pagination = { ...pagination };
          _pagination.total = res.data.webAPIData?.webAPIData
            ? res.data.webAPIData.totalCount
            : res.data.data?.totalCount;
          setPagination(_pagination);
          setTableData(_tableData);
          // 处理排序字段
          handleSortString(_sortString);
          if (_tableData) {
            setSortModalVisible(true);
            setCurrentReportId(_reportDetails[0]?.reportId);
          } else {
            setSortModalVisible(false);
            setCurrentReportId(null);
          }
        } else {
          setSortModalVisible(false);
          setCurrentReportId(null);
          message.error('未能查询到报表数据!');
          let _pagination = { ...pagination };
          _pagination.total = 0;
          _pagination.current = 1;
          setPagination(_pagination);
          setTableData([]);
        }
        if (isInit) setIsInit(false);
        setTableLoading(false);
      })
      .catch((err) => {
        console.log(err);
        setTableLoading(false);
      });
  };
  const getConfigs = () => {
    reportService.getReportDetails({ reportName }).then((res) => {
      if (res.code === 0) {
        setReportConfigs(res.data);
        setConfig(res.data);
        setColumns(returnColumn(res.data));
        setTableStruct(res.data);
        setFirstToGetData(true);
      } else {
        message.error(res.msg);
      }
    });
  };
  /** @description: 在配置项中,isFilter: true 用来渲染控制框;filterRule: 下拉/文本/多选 */
  const getControlsBarConfig = (config) => {
    let _data = config.filter((item) => item.isFilter);
    let _searchPlaceholder = [];
    _data
      .filter((item) => item.filterRule === '文本')
      .forEach((item) => _searchPlaceholder.push(item.fieldAlias));
    setSearchPlaceholder(_searchPlaceholder);
    let _controls = _data.filter((item) => ControlsType.includes(item.filterRule));
    setControls(_controls);
    handleControls(_controls); // 处理控制条,设定默认值
    handleDate(_controls); // 处理日期, 设定默认值
  };
  const getTableHeaderConfig = (config, data) => {
    // setTableStruct(config);
    // setColumns(returnColumn(config, data));
    setAllSortFields(returnSortFields(config));
  };
  const getTableSummaryConfig = (config, summary) => {
    if (summary.length === 0) {
      setSummaryArray([]);
      return false;
    }
    let _summaryConfig = {};
    let _configLength = config.length; // 需要判断
    // 合并列
    let _colSpan = -1;
    let _index = 0;
    config
      .filter((item) => item.isShow)
      .forEach((item, index) => {
        if (item.isStatistics) {
          _index += 1;
          _colSpan = -1;
          _summaryConfig[item.fieldAlias] = {
            fieldName: item.fieldAlias,
            index,
            alignType: item.alignType,
            type: item.statisticsRule,
            isMoney: item.type === '数值' && !!hasMoney(item.configItems),
            configItems: item.configItems,
          };
        } else {
          let _name = `空值行${_index}`;
          if (_colSpan === -1) {
            _colSpan = 1;
          } else {
            _colSpan += 1;
          }
          _summaryConfig[_name] = {
            fieldName: _name,
            colSpan: _colSpan,
          };
        }
      });
    summary.forEach((item) => {
      switch (item.totalType) {
        case '全部':
          setHasTotal(true);
          break;
        case '单页':
          setHasSinglePage(true);
          break;
        default:
          break;
      }
      if (_summaryConfig[item.fieldName]) {
        _summaryConfig[item.fieldName][item.totalType] = item.fieldValue;
      }
    });
    // 增加操作列,总结栏最后一个单元格需要延伸一格
    let _sumArr = Object.values(_summaryConfig);
    if (_sumArr && _sumArr.length)
      _sumArr = _sumArr.map((item, index) => {
        let _item = { ...item };
        if (index === _sumArr.length - 1) _item.colSpan += 1;
        return _item;
      });
    setSummaryArray(_sumArr);
  };

  const changeDate = ({ dateFrom, dateTo }, mode) => {
    setTimeFrom(dateFrom);
    setTimeTo(dateTo);
    setDateMode(mode);
  };
  const mapHandleType = (type) => {
    const _map = {
      文本: handleText,
      多行文本: handleText,
      数值: handleNumber,
      数值标签: handleNumberTag,
      标签: handleTag,
      链接: handleLink,
      功能: handleWidget,
      弹窗: handleModal,
      日期: handleDateString,
      日期时间: handleDateTimeString,
    };
    return _map[type] || _map['文本'];
  };
  const returnSortFields = (data) => {
    return data.map((item) => item.fieldAlias);
  };
  // 处理表格数据,生成表头
  const returnColumn = (config, data) => {
    //0. 常规数据
    //1. 合并表头;
    //2. 四类形态的渲染处理;
    //3. 多列表头排序;剔除掉原有图标,需要自己实现排序的按钮
    let _config = [...config].filter((item) => item.isShow);

    function dataStruct(keyArray, dataIndex, obj, dataObj) {
      if (dataIndex < keyArray.length - 1) {
        if (!obj[keyArray[dataIndex]]) {
          obj[keyArray[dataIndex]] = {};
        }
        let _dataIndex = dataIndex + 1;
        dataStruct(keyArray, _dataIndex, obj[keyArray[dataIndex]], dataObj);
      } else if (dataIndex === keyArray.length - 1) {
        obj[keyArray[dataIndex]] = dataObj;
      }
    }

    let _tempObj = {};
    let _fieldAliasArray = data ? handleDataToGetRowSpanArray(_config, data) : false; // 需要向下合并的字段
    _config.forEach((item) => {
      let _item = {
        title: item.fieldAlias,
        dataIndex: item.fieldAlias,
        key: item.fieldAlias,
        ellipsis: true,
        onCell: (record, rowIndex) => {
          // console.log('Record: ', record); // record是这条记录,index是rowIndex
          // 1. 如果该字段是需要向下合并的,则进入判断
          let _obj = {};
          if (_fieldAliasArray && _fieldAliasArray[item.fieldAlias]) {
            _obj.rowSpan = _fieldAliasArray[item.fieldAlias][rowIndex];
          }
          return _obj;
        },
        render: (value, record) => {
          // 文本、标签、链接、数值
          // @params: item 当前的config数据,提供该字段的各类配置
          //          value 当前单元格的值
          //          record 点击单元格的整行数据
          let rest = [];
          if (item.type === '功能') {
            /*            rest = {
                          showComponent: setDetailsComponentVisible,
                          setDetailsConfig: setDetailConfig,
                        };    */
            rest = [setDetailsComponentVisible, setDetailConfig];
          } else if (item.type === '弹窗') {
            /*            rest = {
                          showModal: setModalVisible,
                          setExtra: setExtra,
                        };*/
            rest = [setModalVisible, setExtra];
          }
          return mapHandleType(item.type)(
            item,
            [undefined, null].includes(value) ? '' : value,
            record,
            ...rest,
          );
        },
      };
      _item.width = (!isNaN(Number(item.columnWidth)) && item.columnWidth) || 200; // 列宽,不设置时默认给200;
      if (item.fixedColumn) _item.fixed = item.fixedColumn; // 固定位置
      _item.align = item.alignType || 'left'; // 单元格内对齐方式
      let _keyArray = (item.fieldGroup || item.fieldAlias || item.fieldName).split(fieldSplitStr);
      // 自定义排序
      let _sortFields = handleSortFields(sortFields);
      if (_sortFields.includes(item.fieldAlias)) {
        _item.sorter = true;
      }
      dataStruct(_keyArray, 0, _tempObj, _item);
      return _item;
    });
    let _tempArray = [];

    function handleObject2Array(obj, arr) {
      Object.keys(obj).forEach((key, index) => {
        if (obj[key].title && obj[key].title === key) {
          arr.push(obj[key]);
        } else {
          arr.push({ title: key, children: [] });
          handleObject2Array(obj[key], arr[index].children);
        }
      });
    }

    handleObject2Array(_tempObj, _tempArray);
    // 增加序号
    _tempArray.unshift({
      title: '序号',
      dataIndex: 'r',
      key: 'r',
      width: 60,
      fixed: 'left',
    });
    // 增加操作列
    if (permission.includes('editBtn') || permission.includes('deleteBtn')) {
      _tempArray.push({
        title: '操作',
        align: 'center',
        width: permission.reduce((final, curr) => {
          if (['editBtn', 'deleteBtn'].includes(curr)) {
            final += 30;
          }
          return final;
        }, 30),
        fixed: 'right',
        render: (text, record) => {
          return (
            <Space className={style.handleColumnWrapper}>
              {record.IsAllow ? (
                <Popconfirm
                  placement="topRight"
                  title={'确认取消关注吗'}
                  icon={<QuestionCircleOutlined />}
                  onConfirm={() => focusProject(record)}
                >
                  <Tooltip title={'点击取消关注'}>
                    <HeartTwoTone twoToneColor="#eb2f96" />
                  </Tooltip>
                </Popconfirm>
              ) : (
                <Popconfirm
                  placement="topRight"
                  title={'确认关注项目吗'}
                  icon={<QuestionCircleOutlined />}
                  onConfirm={() => focusProject(record)}
                >
                  <Tooltip title={'点击添加关注'}>
                    <HeartOutlined />
                  </Tooltip>
                </Popconfirm>
              )}
              {permission.includes('editBtn') && !isLocalDataSource ? (
                <FormOutlined
                  className={style.editButton}
                  onClick={() => {
                    // setEditComponentVisible(true);
                    setModalType('编辑');
                    setCurrentData(record);
                  }}
                />
              ) : (
                ''
              )}
              {permission.includes('deleteBtn') && !isLocalDataSource ? (
                <DeleteOutlined
                  disabled
                  className={style.deleteButton}
                  onClick={() => {
                    Modal.confirm({
                      content: '你确定要删除该数据吗?',
                      onOk: () => {
                        reportService
                          .delReportData({
                            reportName: reportName,
                            userId: USER_ID,
                            key: record.Key,
                          })
                          .then((res) => {
                            if (res.code === 0) {
                              message.success('删除成功!');
                              setGetNewData(!getNewData);
                              // getData(pagination); // 在onOk的回调函数内,打包后的代码会形成闭包
                            }
                          });
                      },
                    });
                  }}
                />
              ) : (
                ''
              )}
            </Space>
          );
        },
      });
    }
    // 统计宽度
    let _x = _tempArray.reduce((final, curr) => {
      return (final += curr.width);
    }, 0);
    setTableX(_x);
    return _tempArray;
  };
  const changeSortField = (value, index, key) => {
    let _selectedSortFields = [...selectedSortFields];
    _selectedSortFields[index][key] = value;
    setSelectedSortFields(_selectedSortFields);
  };
  const addOtherSortFields = () => {
    let _selectedSortFields = [...selectedSortFields];
    _selectedSortFields.push({
      label: '次要排序',
      value: '',
      sort: 'asc',
    });
    setSelectedSortFields(_selectedSortFields);
  };
  const deleteSortField = (index) => {
    let _selectedSortFields = [...selectedSortFields];
    _selectedSortFields.splice(index, 1);
    setSelectedSortFields(_selectedSortFields);
  };
  const setTableHeight = () => {
    if (!tableWrapperRef.current) return;
    const clientHeight = tableWrapperRef.current?.clientHeight || 0;
    const clientWidth = tableWrapperRef.current?.clientWidth || 0;
    const _height = controlRef.current?.clientHeight; // 控制条的高度
    const paginationHeight = 75; // 分页部分的高度
    const tableHeaderHeight = tableHeaderLevel * 40; // 表头高度
    const summaryHeight = summaryArray.length ? 40 * (Number(hasTotal) + Number(hasSinglePage)) : 0; // 总结栏的高度
    const _minus =
      clientHeight - _height - 16 - 4 - tableHeaderHeight - paginationHeight - summaryHeight - 10;
    setListHeight(clientHeight - _height - paginationHeight - 4 - 6 - 16 - 2);
    setTableY(_minus);
  };
  const getTableLevel = (config) => {
    let _level =
      config.reduce((final, curr) => {
        return (final = curr.level > final ? curr.level : final);
      }, 1) || 1;
    setTableHeaderLevel(_level);
  };
  const saveReportListSortFields = (callback) => {
    reportService
      .saveReportListSortFields({
        reportId: currentReportId,
        sortFields: selectedSortFields
          .filter((item) => item.value)
          .map((item) => ({
            fieldAlias: item.value,
            sortType: item.sort,
          })),
      })
      .then((res) => {
        if (res.code === 0) {
          message.success('排序保存成功!');
          callback();
        } else {
          message.error(res.msg);
        }
      });
  };
  /** @description: 判断是否存在【时间】类型的选择,并返回组件;并记录默认值 */
  const handleControls = (controls) => {
    // 过滤出非日期的字段,存储默认值
    let _controls = controls.filter((item) => item.type !== '日期');
    _controls.forEach((item) => {
      let _configItems = item.configItems.split('|');
      _configItems.forEach((str) => {
        if (str.includes('defaultValue=')) {
          controlSelectChange(item.fieldAlias, str.replace('defaultValue=', ''));
        }
      });
    });
  };
  const handleDate = (obj) => {
    let _typeObj = obj.find((item) => item.filterRule === '日期');
    setHasDatePicker(_typeObj ? _typeObj.fieldAlias : '');
    const _configItems = _typeObj?.configItems.split('|') || [''];
    let _defaultDate = _configItems
      .find((item) => item.includes('defaultDate='))
      ?.replace('defaultDate=', '')
      ?.split(',');
    let _defaultModel =
      _configItems.find((item) => item.includes('defaultModel='))?.replace('defaultModel=', '') ||
      'year';
    _defaultDate = MODEL.includes(_defaultModel) ? _defaultDate : 'year'; // 确保值符合要求
    if (_defaultDate && _defaultDate.length > 1) {
      _defaultDate = { dateFrom: moment(_defaultDate[0]), dateTo: moment(_defaultDate[1]) };
    } else if (_defaultDate && _defaultDate.length === 1) {
      _defaultDate = { dateFrom: moment(_defaultDate[0]), dateTo: moment(_defaultDate[0]) };
    } else {
      _defaultDate = { dateFrom: moment(), dateTo: moment() };
    }
    // 给定默认值,初始化时可以加载
    changeDate(
      {
        dateFrom: _defaultDate?.dateFrom.clone().startOf(_defaultModel).format(dateFormat),
        dateTo: _defaultDate?.dateTo.clone().endOf(_defaultModel).format(dateFormat),
      },
      _defaultModel,
    );
    setDefaultDateConfig({
      defaultDate: _defaultDate?.dateFrom,
      defaultModel: _defaultModel,
    });
  };
  const focusProject = (record) => {
    reportService
      .setReportAllow({
        userId: USER_ID,
        reportName: reportName,
        reportKey: record.Key,
      })
      .then((res) => {
        if (res.code === 0) {
          message.success(`${record.IsAllow ? '取消' : '关注'}成功!`);
          getData(pagination);
        } else {
          message.error(`${record.IsAllow ? '取消' : '关注'}失败!`);
        }
      });
  };

  function getRefHeight() {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      let _height = controlRef?.current.clientHeight;
      setControlsHeight(_height);
    }, 100);
  }

  useEffect(() => {
    getConfigs();
  }, []);
  useEffect(() => {
    if (firstToGetData) getData(pagination);
    getRefHeight();
  }, [firstToGetData]);
  useEffect(() => {
    if (tableHeaderLevel) setTableHeight();
  }, [tableHeaderLevel]);
  useEffect(() => {
    if (!isInit) getData(pagination);
  }, [timeFrom, timeTo, sorterObject, filterObject, getNewData]);
  useEffect(() => {
    window.addEventListener('resize', getRefHeight);
    return () => window.removeEventListener('resize', getRefHeight);
  });
  return (
    <div className={style.reportManage} ref={tableWrapperRef}>
      {/* 预留容器,提供给点击后的功能显示 */}
      {detailsComponentVisible ? (
        <div
          className={style.contentWrapper}
          style={{
            position: 'absolute',
            zIndex: 100,
            width: 'calc(100% - 16px)',
            height: 'calc(100% - 16px)',
          }}
        >
          <DetailsComponent
            url={detailConfig.url}
            params={detailConfig.params}
            onCancel={() => setDetailsComponentVisible(false)}
          />
        </div>
      ) : (
        ''
      )}
      {/* 为方便阅读,分开两部分代码 */}
      <div
        className={style.contentWrapper}
        style={{ zIndex: detailsComponentVisible ? -1 : 'auto' }}
      >
        <Row className={style.controlRow} ref={controlRef}>
          <Space style={{ flex: 1 }} size={8} wrap={true}>
            {/*时间搜索控件,确保时间搜索控件在第一个,单独匹配*/}
            {hasDatePicker &&
            defaultDateConfig.defaultDate !== null &&
            permission.includes('filters') ? (
              <DatePickerGroup
                showModels={['all', 'month', 'quarter', 'year', 'custom']}
                onChange={changeDate}
                format={dateFormat}
                defaultModel={defaultDateConfig.defaultModel}
                defaultDate={defaultDateConfig.defaultDate}
              />
            ) : (
              ''
            )}
            {controls && controls.length && permission.includes('filters')
              ? controls
                  .filter((control) => ['下拉', '多选'].includes(control.filterRule))
                  .map((control) => {
                    return (
                      <Form.Item label={control.fieldAlias} key={control.fieldAlias}>
                        <ReturnControlComponent
                          style={{ width: 240 }}
                          type={control.filterRule}
                          reportName={reportName}
                          fieldAlias={control.fieldAlias}
                          configItems={control.configItems}
                          onChange={(e) => controlSelectChange(control.fieldAlias, e)}
                          filterFields={filterFields}
                          filterValues={filterValues}
                          filterObject={addFilterAndSearchParams({
                            reportName: reportName,
                            userId: USER_ID,
                          })}
                        />
                      </Form.Item>
                    );
                  })
              : ''}
            {permission.includes('filters') ? (
              <Form.Item label="快速索引" key={'快速搜索控件'}>
                <ReturnControlComponent
                  placeholder={`请输入${
                    searchPlaceholder.length ? searchPlaceholder.join(',') : '关键字'
                  }搜索`}
                  style={{ width: 240 }}
                  type={'文本'}
                  onChange={(e) => {
                    searchInputChange(e);
                  }}
                  onSearch={searchData}
                />
              </Form.Item>
            ) : (
              ''
            )}
          </Space>
          {permission.includes('sortBtn') ||
          permission.includes('exportBtn') ||
          permission.includes('addBtn') ? (
            <div style={{ width: 270, textAlign: 'end' }}>
              <Space size={8} nowrap>
                {permission.includes('addBtn') && !isLocalDataSource ? (
                  <Form.Item>
                    <Button
                      type={'primary'}
                      title={'自定义排序'}
                      icon={<PlusOutlined />}
                      onClick={() => {
                        setModalType('新增');
                        setCurrentData({});
                      }}
                    >
                      添加
                    </Button>
                  </Form.Item>
                ) : (
                  ''
                )}
                {sortModalVisible && permission.includes('sortBtn') ? (
                  <Form.Item>
                    <Button
                      type={'primary'}
                      title={'自定义排序'}
                      icon={<SortAscendingOutlined />}
                      onClick={() => setModalVisible(true)}
                    >
                      排序
                    </Button>
                  </Form.Item>
                ) : (
                  ''
                )}
                {permission.includes('exportBtn') ? (
                  <Form.Item>
                    <Dropdown style={{ float: 'right' }} overlay={menu}>
                      <Button>
                        <Space>
                          导出
                          <DownOutlined />
                        </Space>
                      </Button>
                    </Dropdown>
                  </Form.Item>
                ) : (
                  ''
                )}
              </Space>
            </div>
          ) : (
            ''
          )}
        </Row>
        <div
          className={style.tableContent}
          style={{ height: `calc(100% - ${controlsHeight || 0}px)` }}
        >
          {columns && columns.length ? (
            <BasicTable
              rowKey={'Key'}
              bordered
              loading={tableLoading}
              dataSource={tableData}
              columns={columns}
              onChange={(pagination, filters, sorter, extra) => {
                setSorterObject(sorter);
              }}
              pagination={permission.includes('pagination') ? pagination : false}
              // 237是内置图片高度
              scroll={{ y: tableData && tableData.length ? `calc(100% - 44px)` : 237, x: tableX }}
              summary={(pageData) => {
                if (summaryArray.length && tableData && tableData.length)
                  return (
                    <Table.Summary fixed>
                      <Table.Summary.Row>
                        {hasSinglePage
                          ? summaryArray.map((item, index) => {
                              if (item.fieldName === '空值行0') {
                                return (
                                  <Table.Summary.Cell
                                    key={`summary_${index}`}
                                    index={0}
                                    colSpan={item.colSpan + 1}
                                  >
                                    <span
                                      style={{
                                        display: 'inline-block',
                                        width: '100%',
                                        textAlign: 'center',
                                      }}
                                    >
                                      小计
                                    </span>
                                  </Table.Summary.Cell>
                                );
                              } else if (item.fieldName.includes('空值行')) {
                                return (
                                  <Table.Summary.Cell
                                    key={`summary_${index}`}
                                    index={0}
                                    colSpan={item.colSpan}
                                  />
                                );
                              } else {
                                return (
                                  <Table.Summary.Cell key={`summary_${index}`} index={0}>
                                    <span
                                      style={{
                                        display: 'inline-block',
                                        width: '100%',
                                        textAlign: item.alignType,
                                      }}
                                    >
                                      {item.type.replace('求', '')}:{' '}
                                      {returnHandledNumber(item.configItems, item['单页'], true)}
                                    </span>
                                  </Table.Summary.Cell>
                                );
                              }
                            })
                          : ''}
                      </Table.Summary.Row>
                      <Table.Summary.Row>
                        {hasTotal
                          ? summaryArray.map((item) => {
                              if (item.fieldName === '空值行0') {
                                return (
                                  <Table.Summary.Cell index={0} colSpan={item.colSpan + 1}>
                                    <span
                                      style={{
                                        display: 'inline-block',
                                        width: '100%',
                                        textAlign: 'center',
                                      }}
                                    >
                                      总计
                                    </span>
                                  </Table.Summary.Cell>
                                );
                              } else if (item.fieldName.includes('空值行')) {
                                return <Table.Summary.Cell index={0} colSpan={item.colSpan} />;
                              } else {
                                return (
                                  <Table.Summary.Cell index={0}>
                                    <span
                                      style={{
                                        display: 'inline-block',
                                        width: '100%',
                                        textAlign: item.alignType,
                                      }}
                                    >
                                      {item.type.replace('求', '')}:{' '}
                                      {returnHandledNumber(item.configItems, item['全部'], true)}
                                    </span>
                                  </Table.Summary.Cell>
                                );
                              }
                            })
                          : ''}
                      </Table.Summary.Row>
                    </Table.Summary>
                  );
              }}
            />
          ) : (
            <div className={style.spinWrapper}>
              <Spin />
            </div>
          )}
        </div>
      </div>
      <Modal
        title={'自定义排序字段'}
        visible={modalVisible}
        onCancel={() => setModalVisible(false)}
        footer={
          <div style={{ display: 'flex', justifyContent: 'space-between' }}>
            <div>
              <Button type={'link'} onClick={() => addOtherSortFields()}>
                增加次要排序
              </Button>
            </div>
            <div>
              <Button onClick={() => setModalVisible(false)}>取消</Button>
              <Button
                type={'primary'}
                onClick={() => {
                  saveReportListSortFields(() => getData(pagination));
                  setModalVisible(false);
                }}
              >
                确认
              </Button>
            </div>
          </div>
        }
      >
        {selectedSortFields.map((item, index) => (
          <Row key={'label'} className={style.controlRow}>
            <Space size={8} wrap={true}>
              <Form.Item label={item.label}>
                <Select
                  style={{ width: 240 }}
                  defaultValue={item.value}
                  value={item.value}
                  onChange={(e) => changeSortField(e, index, 'value')}
                >
                  <Option value="">未选择</Option>
                  {allSortFields.map((item) => (
                    <Option value={item}>{item}</Option>
                  ))}
                </Select>
              </Form.Item>
              <Form.Item>
                <Select
                  style={{ width: 120 }}
                  defaultValue={item.sort}
                  value={item.sort}
                  onChange={(e) => changeSortField(e, index, 'sort')}
                >
                  <Option value={'asc'}>升序</Option>
                  <Option value={'desc'}>降序</Option>
                </Select>
              </Form.Item>
              {index !== 0 ? (
                <Form.Item>
                  <MinusCircleOutlined
                    style={{ color: 'rgba(0,0,0,.65)' }}
                    onClick={() => deleteSortField(index)}
                  />
                </Form.Item>
              ) : (
                ''
              )}
            </Space>
          </Row>
        ))}
      </Modal>
      <Modal visible={extraModal} onCancel={() => setExtraModal(false)} destroyOnClose width={800}>
        {extra}
      </Modal>
      {/* 编辑表单 */}
      <Modal
        title={`${modalType}报表信息`}
        visible={!!modalType}
        width={'80%'}
        footer={null}
        // visible={true}
        destroyOnClose
        onCancel={() => setModalType('')}
      >
        <ReportEditForm
          modalType={modalType}
          reportDetails={tableStruct}
          reportData={currentData}
          onCancel={() => {
            setModalType('');
            getData(pagination);
          }}
          reportName={reportName}
        />
      </Modal>
    </div>
  );
};
const mapStateToProps = (state) => {
  const allWidgets = state.getIn(['global', 'globalConfig', 'allWidgets']);
  let _flatWidgets = [];
  const flatWidgets = (arr) => {
    arr.forEach((item) => {
      if (item.widgets && item.widgets.length) {
        flatWidgets(item.widgets);
      } else {
        _flatWidgets.push(item);
      }
    });
  };
  flatWidgets(allWidgets);
  return {
    allWidgets: _flatWidgets,
  };
};
export default connect(mapStateToProps, null)(ReportsManage);