import React from 'react';
import Pagination from 'antd/lib/Pagination';
import Spin from 'antd/lib/Spin';
import message from 'antd/lib/message';
import Button from 'antd/lib/Button';
import Modal from 'antd/lib/modal';
import { Icon, render as renderAmis } from '../../../../index'
import { Renderer, RendererProps } from '../../../../factory';
import { BaseSchema, SchemaApi } from '../../../../Schema';
import { Action, SchemaNode } from '../../../../types';
import { filter } from '../../../../utils/tpl';
import { ScopedContext, IScopedContext } from '../../../../Scoped';
import { CN } from './locale/pagination';
import { findDOMNode } from 'react-dom';
import { LionTableStore, ILionTableStore } from '../../../../store/liontable';
import { evalExpression } from '../../../../utils/tpl';
import { getLodop } from '../../../../utils/print/LodopFuncs'
import { templateDesign } from '../../../../utils/print'
import { buildLabelTemplate } from '../../../../utils/print/util';
import { ModalPrint } from '../../LabelPrint';
import { RendererEnv } from '../../../../env';
import {
  GenericColContainer,
} from './assembly/generic/index'
import {
  CommonHeader,
  CommonFixHeader
} from './assembly/table/header/index'
import { LeftArea } from './assembly/table/leftArea/index'
import { RightArea } from './assembly/table/rightArea/index'
import { IntermediateArea } from './assembly/table/intermediateArea/index'
import LionTableInterrogator from './assembly/Interrogator/index'
import SpreadSelection from './assembly/spreadSelection/index'
import EmptyPlaceHolder from './assembly/placeHolder';
import omit from 'lodash/omit';
import './style/baseCss/popover.css'
import './style/baseCss/index.css';
import './components/MainExport/MainExport.css';
import './scss/toolbar.scss';
import './scss/table.scss'
import './scss/tbody.scss';
import './scss/fixTbody.scss'

interface LionTableState {
  fixLeft: number; // 左侧滚动条位置
  tableBody: any; // 表格体引用
  fixColumns: any[]; // 从表列配置
  selectList: any; // 被选中的数据行
  SonList: any; // 从表数据
  checkAll: boolean; // 选中所有数据
  loading: boolean; // 表格加载loading
  pageData: any[]; // 主表分页数据
  totalSize: number;
  pageSize: number;
  page: number;
  wrapper: number;
  _container_height: any;
  table_height: any;
  storageSource: any;
  pageSelectList: any;
  colHideList: any;
  hasFetch: boolean; // 标记是否请求过
  ModalProps: any;
  printType?: string
  surfaceItemWidth: number;
  colSpan: number;
  primaryElevae: number;
  subordinateElevae: number;
  toolSwitch: boolean;
}

interface ColumnObject {
  label?: string;

  name?: string;

  group?: Array<any>;

  hideLabel?: boolean;

  hiddenOn?: string;

  [propName: string]: any;
}



export interface LionTestTableSchema extends BaseSchema {
  type: 'lion-table';
  /*
    组件类型
  */
  filter?: any;
  /*
    查询器表单
  */
  headerToolbar: Array<any>;
  /*
    头部按钮组（非选中才能点击，普通按钮)
  */
  bulkActions: Array<any>;
  /*
    头部按钮组（批量，有数据被选中才能点击)
  */
  primaryField?: string;
  /*
    主表行的主键字段
  */
  columns: Array<ColumnObject>;
  /*
    子表列配置
  */
  api?: SchemaApi;
  /*
    数据源请求地址及参数
  */
  list_columns: Array<ColumnObject>
  /*
    主表列配置
  */
  source: string;
  /*
    根据字段获取响应地内容中的表格数据，默认为items
  */
  checkbox: boolean;
  /*
    是否使用复选框
  */
  detailTableField?: string;
  /*
    表示主表中的子表的标识符，用于提取主表中的子表数据
  */
  style?: any;
  /*
    自定义表格的样式对象
  */
  subTableTitle?: string;
  /*
    从表弹出框标题
   */
  width?: number;
  /*
    设置表格宽度
  */
  totalTab?: {
    key: number;
    totalNum: string | number;
  }
  /*
    当前tab对应的标记
  */
  setTotalNum?: (key: string | number, totalNum: number, tableName: string) => void;
  /*
    用于当表格使用tabs组件包裹时，表格初始化完成后，用于改变tabs上的标签的内容
  */
  onAction?: (
    e: React.UIEvent<any> | void,
    action: Action,
    ctx: object,
    throwErrors: boolean,
    delegate?: IScopedContext
  ) => any;
  /*
    按钮触发器
  */
  subSchemaApi?: SchemaApi;
  /*
    查看全部子表内容的api
  */
  isDialogMode?: boolean;
  /*
  是否处于弹窗模式下
  */

  initFetch?: boolean;
  /*
    初始是否拉取数据，默认为true
  */
  keepItemSelectionOnPageChange?: boolean;
  /*
    是否开启跨页选中
  */
  perPageAvailable?: number[];
  /*
    分页
  */
  perPage?: number;
}

interface LionTestTableContextSchema {
  env?: RendererEnv;
  handleAction?: Function;
  primaryField?: string;
  subSchemaApi?: SchemaApi;
  render?: (region: string, node: SchemaNode, props?: any) => JSX.Element;
  subTableTitle?: string;
}

export const LionTestTableContext = React.createContext<LionTestTableContextSchema>({})

export interface LionTestTableProps extends RendererProps, Omit<LionTestTableSchema, 'type' | 'className' | 'data'> { store: ILionTableStore; }

const calcGap = (rest: number = 0) => {
  // window.document.documentElement.clientHeight - 20 - (document.querySelector('.ant-tabs-content')?.querySelector('.antd-Tabs-links') ? 32 : 0),
  let rootDom: Element | null = document.querySelector('.ant-tabs-content');

  let height: number = rootDom?.clientHeight! - 20;

  return height - rest
}

const calcInnerWidth = () => {
  let clientWidth: number = document.querySelector('.ant-tabs-content')?.clientWidth!;
  // document.documentElement.clientWidth || document.body.clientWidth 直接获取耗时差距太大，暂不使用
  return clientWidth > 1680 ? clientWidth : 1680
}

const antiShake = (callBack: Function, wait = 0, rest?: unknown) => {
  let timer: any = null;
  return () => {
    if (timer) {
      clearTimeout(timer);
      timer = null;
    }
    timer = setTimeout(() => {
      callBack(rest)
    }, wait)
  }
}


export class LionTestTable extends React.Component<LionTestTableProps, LionTableState>{

  static contextType = ScopedContext

  rawTableData: { items: any[], total: number } = { items: [], total: 0 }

  constructor(props: LionTestTableProps, context: IScopedContext) {
    super(props);

    this.state = {
      fixLeft: 0, // 左侧滚动条位置
      tableBody: React.createRef() as any, // 表格体引用
      fixColumns: [], // 从表列配置
      selectList: {} as any, // 被选中的数据行
      pageSelectList: {} as any,
      SonList: {} as any,
      checkAll: false, // 选中所有数据
      loading: true, // 表格加载loading
      pageData: [],
      totalSize: 0,
      pageSize: props.perPage || 10,
      page: 1,
      storageSource: {} as any,
      colHideList: {} as any,
      wrapper: calcInnerWidth(),
      _container_height: calcGap(),
      table_height: calcGap(40 + 46 + (props?.filter ? 50 : 0) + ((props?.headerToolbar?.length > 0 || props?.bulkActions?.length > 0) ? 40 : 10)),
      hasFetch: false, // 标记是否请求过
      ModalProps: {
        title: '打印选项',
        show: false,
        onHide: null
      },
      printType: undefined,
      surfaceItemWidth: 0,
      colSpan: 0,
      primaryElevae: 0,
      subordinateElevae: 0,
      toolSwitch: false,
    }

    this.handleAction = this.handleAction.bind(this);

    const scoped = context;
    scoped.registerComponent(this);
  }

  static defaultProps: Partial<LionTestTableProps> = {
    source: 'items',
    ids: '_id',
    store: LionTableStore as any
  }

  _uploadRef: any;

  get baseUrl() {
    const { env } = this.props;
    return env?.axiosInstance?.defaults?.baseURL || env?.ajaxApi;
  }

  get uiWorker() {
    let url = !this.baseUrl ? (location.href.includes('localhost') ? '/public/worker/index.js' : '/worker/index.js') : './public/worker/index.js';

    let worker = new Worker(url);

    worker.onmessage = (e) => {
      this.receiveMessage(e.data.data)
    }
    return worker
  }

  get dataWorker() {
    let url = !this.baseUrl ? (location.href.includes('localhost') ? '/public/worker/dataWorker.js' : '/worker/dataWorker.js') : './public/worker/dataWorker.js';
    let worker = new Worker(url);
    worker.onmessage = (e) => {
      this.receiveMessage(e.data.data)
    }
    return worker
  }

  get dataSource() {
    return this.state.pageData
  }

  _bindRef = (ref: any) => {
    this._uploadRef = ref;
  }

  receiveMessage(content: any) {
    // let union = {};
    // if (this.props.keepItemSelectionOnPageChange) {
    //   const { SonList, pageData, storageSource, colHideList, pageSelectList } = this.state;
    //   union = {
    //     SonList: { ...SonList, ...content.SonList },
    //     pageData: [...pageData, ...content.pageata],
    //     storageSource: { ...storageSource, ...content.storageSource },
    //     colHideList: { ...colHideList, ...content.colHideList },
    //     pageSelectList: { ...pageSelectList, ...content.pageSelectList }
    //   }
    // }
    this.setState({
      ...content,
      // ...union
    });
  }

  // 主表选中行
  get checkList() {
    const { selectList, storageSource } = this.state;
    let _checkList = Object.entries(selectList).filter((item: any) => {
      return item[1] === true
    }).map(item => {
      return item[0]
    })
    const newList: Array<object> = [];
    _checkList.forEach((item: any) => {
      if (storageSource[item]) newList.push(storageSource[item])
    })
    return newList
  }

  get record_ids() {
    const { primaryField } = this.props;
    const { pageData } = this.state;
    let _ids: string = '';

    pageData.forEach((record: any) => {
      _ids += record.hasOwnProperty(primaryField) ? record[primaryField!] + ',' : ''
    })
    return _ids.slice(0, _ids.length - 1)
  }

  get ids() {
    let _ids: string = '';
    const { primaryField } = this.props;
    this.checkList.map((_select: any) => {
      _ids += _select.hasOwnProperty(primaryField) ? _select[primaryField!] + ',' : ''
    })
    return _ids.slice(0, _ids.length - 1)
  }

  // 计算左侧固定表格的宽度
  get leftTableWidth() {
    const { fixColumns } = this.state;
    let count = 0;
    fixColumns.forEach((item: any, index: number) => {
      if (item?.fixed === 'left') {
        count += item?.width
      }
    })
    return count
  }

  // 计算右侧固定表格的宽度
  get rightTableWidth() {
    const { fixColumns } = this.state;
    let count = 0;
    fixColumns.forEach((item: any, index: number) => {
      if (item?.fixed === 'right') {
        count += item?.width
      }
    });
    return count
  }

  calcSubordinateSize(columns: any) {
    let count = columns.reduce((prev: any, current: any, index: number) => {
      return prev + (current?.width ?? 0)
    }, 0)
    return count
  }

  get surfaceWidth() {
    const { list_columns } = this.props;
    let count = list_columns.reduce((prev, current, index) => {
      return prev + (current?.width ?? 0)
    }, 0)
    return count
  }

  initSource(paramsField: any): void {
    const { env, data, initFetch = true } = this.props;
    let _data = {
      ...paramsField,
      ...data,
      ...data?.__super
    }

    const updateState: any = {}

    if (!initFetch) {
      this.generateUI({ loading: false, ...updateState });
      return;
    }

    try {
      env.fetcher(this.props?.api!, _data).then((res: any) => {

        if (!this.state.hasFetch) {
          updateState.hasFetch = true
        }
        if (res?.status === 0) {
          this.rawTableData = res?.data
          this.generatePageConfig(res?.data ? res?.data : {}, updateState);
        } else {
          this.setState({
            loading: false
          })
          throw new Error(res?.msg);
        }
        this.props?.setTotalNum && this.props?.setTotalNum(this.props.totalTab?.key!, res?.data?.total, this.props?.name)
      }).catch((e: Error) => {
        env?.notify("error", e.message)
      })
    } catch (err: any) {
      message.error(err);
      this.setState({
        loading: false
      })
    }
  }

  requestFilterSource = (paramsField: any, isFilter: boolean = false, load: 'ui' | 'data', asynsUpdateState: any = {}): void => {
    const { env, data } = this.props;

    let updateState: any = asynsUpdateState;

    let _data = {
      ...paramsField,
      ...data,
      ...data?.__super
    }

    this.setState({
      loading: true
    })

    try {
      env.fetcher(this.props?.api!, _data).then((res: any) => {

        if (!this.state.hasFetch) {
          updateState.hasFetch = true
        }

        if (res?.status === 0) {
          this.rawTableData = res?.data
          if (load === 'ui') {
            this.generatePageConfig(res?.data ? res?.data : {}, updateState);
          } else {
            this.extractDataSource(res?.data ? res?.data : {}, updateState)
          }
        } else {
          this.setState({
            loading: false
          })
          throw new Error(res?.msg);
        }
        this.props?.setTotalNum && this.props?.setTotalNum(this.props.totalTab?.key!, res?.data?.total, this.props?.name)
      }).catch((e: Error) => {
        env?.notify("error", e.message)
      })
    } catch (err: any) {
      message.error(err);
      this.setState({
        loading: false
      })
    }
  }

  initScrollShadow(target?: any) {
    // 滚动主体
    const scrollBody: any = target ? target : findDOMNode(this);

    const { fixColumns } = this.state;

    let scrollClientWidth: number = this.state.wrapper > this.calcSubordinateSize(fixColumns) ? this.state.wrapper : this.calcSubordinateSize(fixColumns)

    // 左侧固定表格
    const fixLeftTable: any = target ? target.parentElement.parentElement.querySelector('.lion-table-container-fixed-wrapper--left') : scrollBody.querySelector('.lion-table-container-fixed-wrapper--left');
    // 右侧固定表格
    const fixRightTable: any = target ? target.parentElement.parentElement.querySelector('.lion-table-container-fixed-wrapper--right') : scrollBody.querySelector('.lion-table-container-fixed-wrapper--right');

    // 滚动主体的向左滚动距离大于0且左侧固定表格不存在阴影class时，添加阴影效果
    if (scrollBody.scrollLeft > 0 && fixLeftTable?.className.indexOf('lion-talbe--fix--left--shadow') === -1) {
      fixLeftTable.className = fixLeftTable.className + ' lion-talbe--fix--left--shadow'
    }

    // 滚动主体的向左滚动距离小于等于0，移除左侧表格的阴影class
    if (scrollBody?.scrollLeft <= 0) {
      fixLeftTable.className = fixLeftTable?.className.replace(' lion-talbe--fix--left--shadow', '')
    }

    if (target) {
      // 滚动主体的clientWidth + scrollLeft 大于等于 滚动主体的滚动条长度，说明到最右边
      if (Math.floor(scrollBody.clientWidth + scrollBody.scrollLeft) >= scrollBody.scrollWidth) {
        fixRightTable.className = fixRightTable.className.replace(' lion-talbe--fix--right--shadow', '')
      }

      // 滚动主体的clientWidth + scrollLeft 小于 滚动主体的滚动条长度
      if ((Math.floor(scrollBody.clientWidth + scrollBody.scrollLeft) < scrollBody.scrollWidth && fixRightTable.className.indexOf('lion-talbe--fix--right--shadow') === -1)) {
        fixRightTable.className = fixRightTable.className + ' lion-talbe--fix--right--shadow'
      }
      return;
    }

    // 滚动主体的clientWidth + scrollLeft 大于等于 滚动主体的滚动条长度，说明到最右边
    if (scrollBody.scrollWidth >= scrollClientWidth) {
      fixRightTable.className = fixRightTable.className.replace(' lion-talbe--fix--right--shadow', '')
    }

    // 滚动主体的clientWidth + scrollLeft 小于 滚动主体的滚动条长度
    if (scrollBody.scrollWidth < scrollClientWidth && fixRightTable.className.indexOf('lion-talbe--fix--right--shadow') === -1) {
      fixRightTable.className = fixRightTable.className + ' lion-talbe--fix--right--shadow'
    }

  }

  // 表头选择框选中
  onCheckAllChange = (e: any, isClear?: boolean) => {
    e.preventDefault();

    const pageSelectList = this.state.pageSelectList;

    const selectList = this.state.selectList;

    const { checkAll } = this.state;

    const _checkAll = isClear ? false : !checkAll

    Object.keys(pageSelectList).forEach((item: any) => {
      selectList[item] = _checkAll;
      pageSelectList[item] = _checkAll;
    });

    this.setState({
      selectList: selectList,
      checkAll: _checkAll,
      pageSelectList: pageSelectList
    });
  }

  handleSectionChange = (e: React.MouseEvent, current: string, isClear: boolean) => {
    e.preventDefault()

    if (isClear) {
      this.onCheckAllChange(e, isClear)
    } else {
      this.handleMasterChange(e, current)
    }
  }

  // 主表选择框被选中时
  handleMasterChange = (e: any, current: any) => {
    e.preventDefault();
    // 点击时阻止默认事件
    const pageSelectList = this.state.pageSelectList;

    const selectList = this.state.selectList;

    let checkAll;
    // 选中所有数据

    selectList[current] = !selectList[current];

    pageSelectList[current] = selectList[current];

    // 判断是否所有从表数据均被选中，若被选中则给表头选择框添加选中效果
    checkAll = Object.values(pageSelectList).every((item: any) => {
      if (item === false) {
        return false
      }
      return true
    });

    this.setState({
      selectList: selectList,
      checkAll: checkAll,
      pageSelectList: pageSelectList
    });
  }

  extractDataSource(data: any, willUpdateState: any = null) {
    const { source, primaryField, keepItemSelectionOnPageChange, detailTableField } = this.props;
    this.dataWorker.postMessage({
      message: "generateData",
      data: {
        data,
        source,
        primaryField,
        keepItemSelectionOnPageChange,
        detailTableField,
        selectList: this.state.selectList
      },
      willUpdateState
    })
  }

  generateUI(willUpdateState: any = null) {
    const { checkbox, list_columns, isDialogMode, columns } = this.props;
    let adaptiveWidth: number = this.state.wrapper;
    if (isDialogMode) {
      let thisParent = findDOMNode(this)?.parentElement;
      adaptiveWidth = (thisParent?.clientWidth! > 500 ? thisParent?.clientWidth! : 500)
    }

    const {
      _container_height,
      table_height
    } = this.calcHeight()

    this.uiWorker.postMessage({
      message: "createUI",
      data: {
        checkbox,
        list_columns,
        columns,
        wrapper: adaptiveWidth,
        primaryTdSize: this.surfaceWidth,
        table_height,
        _container_height
      },
      willUpdateState
    })
  }

  generatePageConfig(data: any, willUpdateState: any = null) {
    const { checkbox, source, list_columns, isDialogMode, columns, primaryField, keepItemSelectionOnPageChange, detailTableField } = this.props;
    // 自适应宽度。屏幕宽度小于1680时按1680算，其他情况按屏幕宽度算
    let adaptiveWidth: number = this.state.wrapper;
    if (isDialogMode) {
      let thisParent = findDOMNode(this)?.parentElement;
      adaptiveWidth = (thisParent?.clientWidth! > 500 ? thisParent?.clientWidth! : 500)
    }
    const {
      _container_height,
      table_height
    } = this.calcHeight()

    this.uiWorker.postMessage({
      message: "generateUI",
      data: {
        checkbox: checkbox,
        list_columns,
        columns,
        wrapper: adaptiveWidth,
        primaryTdSize: this.surfaceWidth,
        data,
        source,
        primaryField,
        keepItemSelectionOnPageChange,
        detailTableField,
        selectList: this.state.selectList,
        _container_height: _container_height,
        table_height
      },
      willUpdateState
    })
  }

  // 表格滚动条拖动时给固定的列添加或删除阴影效果
  handleScroll = (e: any) => {

    const { currentTarget } = e;

    const { scrollLeft, scrollTop } = currentTarget;

    this.initScrollShadow(currentTarget)
    const fixBodyers: any = currentTarget.parentElement.parentElement.getElementsByClassName('lion-table-container-fixed-body');


    const tableHeaders: any = currentTarget.parentElement.parentElement.getElementsByClassName('lion-table-header');

    for (let i = 0; i < fixBodyers.length; i++) {
      fixBodyers[i].scrollTop = scrollTop
    }

    if (tableHeaders.length > 0) {
      tableHeaders[0].scrollLeft = scrollLeft;
    }
  };

  showTotal = () => {
    const { page, pageSize, totalSize } = this.state;
    const _page = totalSize === 0 ? 0 : page;
    const total = totalSize;
    const currentTotal = total === 0 ? 0 : Math.ceil(total / pageSize);

    return `${_page}/${currentTotal} 总共：${totalSize} 项`;
  }

  // 点击展开或收起操作
  handleOpenCol = (primaryField: string) => {
    const { colHideList } = this.state;

    this.setState({
      colHideList: {
        ...colHideList,
        [primaryField]: !colHideList[primaryField]
      },
    })

  }

  handleAddClass = (arr: any, tabIndex: number) => {
    Array.from(arr).forEach((_node: any) => {
      if (_node?.attributes.tabindex.nodeValue === tabIndex) {
        _node.className += ' tr--hover'
      }
    })
  }

  handleTrMouseOver = (e: any) => {
    if (e.currentTarget.className.indexOf('tr--hover') !== -1) {
      return;
    }
    const _body: any = findDOMNode(this)
    const bodyTable: any = _body.querySelector('.lion-table-body');
    // 左侧固定表格
    const fixLeftTable: any = _body.querySelector('.lion-table-container-fixed-wrapper--left');
    // 右侧固定表格
    const fixRightTable: any = _body.querySelector('.lion-table-container-fixed-wrapper--right');

    const bodyTr = bodyTable.getElementsByClassName('tbody-tr--column--white');
    const fixLeftTr = fixLeftTable.getElementsByClassName('tbody-tr--column--white');
    const fixRightTr = fixRightTable.getElementsByClassName('tbody-tr--column--white');
    this.handleAddClass(bodyTr, e.currentTarget.attributes.tabindex.nodeValue)
    this.handleAddClass(fixLeftTr, e.currentTarget.attributes.tabindex.nodeValue)
    this.handleAddClass(fixRightTr, e.currentTarget.attributes.tabindex.nodeValue)
  }

  handleTrMouseOut = (e: any) => {

    const _body: any = findDOMNode(this);

    const bodyTable: any = _body?.querySelector('.lion-table-body') as any;
    // 左侧固定表格
    const fixLeftTable: any = _body?.querySelector('.lion-table-container-fixed-wrapper--left');
    // 右侧固定表格
    const fixRightTable: any = _body?.querySelector('.lion-table-container-fixed-wrapper--right');

    const bodyTr = bodyTable.getElementsByClassName('tbody-tr--column--white');
    const fixLeftTr = fixLeftTable.getElementsByClassName('tbody-tr--column--white');
    const fixRightTr = fixRightTable.getElementsByClassName('tbody-tr--column--white');

    this.handleRemoveClass(bodyTr)
    this.handleRemoveClass(fixLeftTr)
    this.handleRemoveClass(fixRightTr)
  }

  handleRemoveClass = (arr: any) => {
    Array.from(arr).forEach((_node: any) => {
      _node.className = _node.className.replace('tr--hover', '')
    })
  }

  handlePageSizeChange = (page: number, pageSize: number) => {
    if (!this.props.keepItemSelectionOnPageChange) {
      this.setState({ selectList: [] })
    }

    if (this._uploadRef) {
      this._uploadRef?.handleBulkChange({ perPage: pageSize, page: page });
    }

    this.requestFilterSource({ perPage: pageSize, page: page }, false, 'data', {
      page,
      pageSize,
      checkAll: false
      // pageSelectList: {}
    });
  }

  MonitorPageChanges = (e: any) => {
    const { isDialogMode, checkbox, list_columns, columns } = this.props;
    let wrapper = calcInnerWidth();
    if (isDialogMode) {
      let thisParent = findDOMNode(this)?.parentElement;
      wrapper = (thisParent?.clientWidth! > 500 ? thisParent?.clientWidth! : 500)
    }

    const _wrapper: number = Math.ceil(wrapper);

    const {
      _container_height,
      table_height
    } = this.calcHeight()


    if (_wrapper > 1680) {

      this.uiWorker.postMessage({
        message: "screenTurn",
        data: {
          checkbox,
          list_columns,
          columns,
          wrapper: _wrapper,
          primaryTdSize: this.surfaceWidth,
          _container_height: _container_height,
          table_height
        },
        willUpdateState: null
      })
    }
  }

  calcHeight() {
    let isTab = this.props.totalTab;
    let _dis = 10;
    if (this.props.filter) _dis += 52
    if ((this.props.headerToolbar?.length > 0 || this.props?.bulkActions?.length > 0)) _dis += 30
    if (isTab) _dis += 32;
    // if (this.props.keepItemSelectionOnPageChange) _dis += 35
    let _page_height: any = calcGap();
    let table_height = _page_height - 46 - 40 - _dis;
    if (this.props.isDialogMode) {
      table_height -= 110
    }
    return {
      _container_height: _page_height,
      table_height
    }
  }

  MonitorTableChanges = (e?: any) => {
    const {
      _container_height,
      table_height
    } = this.calcHeight()
    this.setState({
      _container_height: _container_height,
      table_height
    })
  }

  handleFilterParams(value: any) {
    const { page, pageSize } = this.state;
    this._uploadRef?.handleBulkChange({ perPage: pageSize, page: page });
    const filterParams = this._uploadRef ? this._uploadRef?.props?.data : { perPage: pageSize, page: page };
    this.requestFilterSource({ ...value, ...filterParams }, true, 'data')
  }

  reloadTarget(reload: string, ctx: any, callBack?: () => void) {
    const scoped = this.context as IScopedContext;
    // callBack && callBack();
    scoped.reload(reload, ctx);
    // 用于刷新目标组件
  }

  closeTarget(target: string) {
    const scoped = this.context as IScopedContext;
    scoped.close(target);
  }

  reload(subPath: string, query: any, ctx: any): void {
    this.handleFilterParams(ctx)
  }

  receive(value: any, subPath: any): void {
    this.handleFilterParams(value)
  }

  doAction(query: any, ctx: any): void {
    this.handleFilterParams(ctx)
  }

  handleAction = async (
    e: React.UIEvent<any> | void,
    action: Action,
    ctx: any,
    callBack?: () => void,
    throwErrors: boolean = false,
    delegate?: IScopedContext
  ): Promise<any> => {
    const { env, store, messages, onAction } = this.props;
    if (action.actionType === 'ajax') {
      store.setCurrentAction(action);
      const res = await store
        .lionSaveRemote(action.api as string, { ...store.data, ...ctx }, {
          successMessage:
            (action.messages && action.messages.success) ||
            (messages && messages.saveSuccess),
          errorMessage:
            (action.messages && action.messages.failed) ||
            (messages && messages.saveSuccess)
        }).then(response => {

          const redirect =
            action.redirect && filter(action.redirect, store.data);
          redirect && env.jumpTo(redirect, action);
          action.reload && this.reloadTarget(action.reload, { ...store.data, ...ctx });
          return false
        }).catch((error) => { console.info(error) })
      return res
    } else if (action.actionType === 'export') {
      store.setCurrentAction(action);
      let exportData: any = action?.exportType === 2 ? ctx : {};

      exportData = { ...exportData, ...this?._uploadRef?.props?.store?.data };

      exportData.primaryField = this.props.primaryField;
      exportData.selectedItems = this.checkList;
      exportData.ids = (action?.exportType && action?.exportType === 2 ? ctx[this.props.primaryField!] : this.ids);
      store.openLionExport(exportData, env)
      return false
    } else if (action.actionType === 'loginAmazon') {
      store.setCurrentAction(action);
      store.openAmazonLoginPage(ctx, env)
      return false
    } else if (action.actionType === 'label-design') {
      templateDesign(ctx, value => {
        Modal.confirm({
          title: '确认提交该模板吗？',
          okText: '确认',
          cancelText: '取消',
          getContainer: env.getModalContainer,
          onOk: () => {
            if (action.api) {
              const labelTemplate = buildLabelTemplate(value)
              const tableFields = labelTemplate.labelTables.map(table => table.fieldName ?? '').join(',')
              env.fetcher(action.api, {
                tableFields,
                tempId: ctx.TEMP_ID,
                content: value
              }).then((res) => {
                if (res.status === 0) {
                  message.success(res.msg);
                  const { page, pageSize } = this.state;
                  const filterParams = this._uploadRef ? this._uploadRef?.props?.data : { perPage: pageSize, page: page };
                  this.requestFilterSource(filterParams, false, 'data')
                } else {
                  message.error(res.msg)
                }
              })
            }
          }
        })
      })
    } else if (action.actionType === 'label-print' || action.actionType === 'bill-print' || action.actionType === 'report-print') {
      // Jay
      store.setCurrentAction(action);
      const { primaryField } = this.props
      const { translate: __ } = this.props
      const LODOP = getLodop()
      if (LODOP) {
        this.setState({
          ModalProps: {
            ...action,
            title: __('CRUD.printOptions'),
            show: true,
            isFilePrint: false,
            isRow: true,
            ctx: { ...ctx, primaryField },
            data: this.rawTableData,
            onHide: () => { this.setState({ printType: undefined }) },
          },
          printType: action.actionType.slice(0, action.actionType.indexOf('-')) as any
        })
      }
    } else {
      onAction?.(e, action, { ...store.data, ...ctx }, throwErrors, delegate || this.context);
      return false
    }
  }

  /**
    * Jay
    * 标签、文件打印
    */
  renderPrint(ctx: { items: any[], selectedItems: any[], ids: string, primaryField: string, }, schema?: any, isFilePrint?: boolean) {
    const {
      translate: __,
      classnames: nx
    } = this.props;
    // const { selectedItems } = ctx
    const disabled = schema.disabled || evalExpression(schema.disabledOn, ctx)

    return (
      <>
        <Button
          type="primary"
          className={nx(schema._className, { 'is-disabled': disabled })}
          disabled={disabled}
          onClick={() => {
            const LODOP = getLodop()
            if (LODOP) {
              this.setState({
                ModalProps: {
                  ...schema,
                  title: __('CRUD.printOptions'),
                  show: true,
                  ctx,
                  onHide: () => { this.setState({ printType: undefined }) },
                  query: this._uploadRef?.props?.store?.data
                },
                printType: isFilePrint ? 'file' : schema.actionType === 'label-print' ? 'label' : 'bill'
              })
            }
          }}
        >
          {__(schema.label ? schema.label : !isFilePrint ? 'CRUD.labelPrint' : 'CRUD.filePrint')}
        </Button>
      </>
    );
  }

  // 渲染头部按钮及批量按钮
  renderToolBars(toolBars: any, type: string) {
    if (!toolBars?.length) return [];

    const _className = type === 'header' ? 'blukAction' : (this.checkList?.length > 0 ? "blukAction" : "blukAction is-disabled");
    const _disabled = type === 'header' ? false : (this.checkList?.length > 0 ? false : true);

    const toolBarList: [element: JSX.Element, aligh?: 'left' | 'right'][] = []

    toolBars?.length > 0 && toolBars?.forEach((_toolBar: any, _toolIndex: number) => {
      const align = _toolBar.align
      let _data: any = {};

      _data.selectedItems = this.checkList;
      _data.ids = this.ids;
      _data.items = this.dataSource;
      _data.record_ids = this.record_ids;

      if (_toolBar.type === 'label-print') {
        toolBarList.push([this.renderPrint(_data, { ..._toolBar, _className }), align]);
      } else if (_toolBar.type === 'file-print') {
        toolBarList.push([this.renderPrint(_data, { ..._toolBar, _className }, true), align]);
      } else if (_toolBar.type === 'reload') {
        const { render, translate: __, } = this.props
        let reloadButton = {
          label: _toolBar.label || '',
          icon: _toolBar.icon || 'fa fa-sync',
          tooltip: __('reload'),
          tooltipPlacement: 'top',
          type: 'button'
        };
        if (typeof toolbar === 'object') {
          reloadButton = { ...reloadButton, ...omit(toolbar, ['type', 'align']) };
        }
        toolBarList.push([render(`toolbar/${1}`, reloadButton, {
          onAction: () => {
            const { page, pageSize } = this.state;
            const filterParams = this._uploadRef ? this._uploadRef?.props?.data : { perPage: pageSize, page: page };
            this.requestFilterSource(filterParams, false, 'data')
          }
        }), align])
      } else {
        toolBarList.push([renderAmis(_toolBar, {
          className: _className,
          key: _toolIndex,
          disabled: _disabled,
          data: _data,
          onAction: this.handleAction
        }), align])
      }

    })
    return toolBarList
  }


  // 表格头部工具栏渲染
  renderHeaderToolbars(): JSX.Element {
    const { headerToolbar, bulkActions } = this.props;

    const headers = this.renderToolBars(headerToolbar, 'header')
    const bulks = this.renderToolBars(bulkActions, 'bulk')
    const toolBars = headers.concat(bulks)
    const left: any[] = []
    const right: any[] = []
    toolBars.forEach(toolBar => {
      const [element, align] = toolBar
      if (align !== 'right') {
        left.push(element)
      } else {
        right.push(element)
      }
    })
    return <div className="lion-table-header-toolbar">
      <div className="lion-nav-operate-group">
        <div className='lion-nav-operate-group-left'>
          {left}
        </div>
        <div className='lion-nav-operate-group-right'>
          {right.length > 0 && <div className={'lion-nav-operate-group-right-content'} style={{ width: this.state.toolSwitch ? 18 : `calc(${right.length} * 55px + 18px)` }}>
            <div className={'lion-nav-operate-group-right-content-body'} style={{ width: `calc(${right.length} * 55px)` }}>
              {right}
            </div>
            <div className={'lion-nav-operate-group-right-content-icon'} onClick={() => { this.setState({ toolSwitch: !this.state.toolSwitch }) }}>
              <Icon icon={'#icon-tooltool_pickup'} className="icon" symbol />
            </div>
          </div>}
        </div>
      </div>
      {/* <div className="lion-nav-tool-group">
      </div> */}
    </div>
  }

  // 加载表格数据区域
  renderTable() {
    const { primaryElevae, subordinateElevae, pageData, fixColumns, surfaceItemWidth, SonList, colHideList, colSpan } = this.state;

    const { list_columns, primaryField, columns } = this.props;
    //没有操作列的时候多合并一列
    const calcColSpan = columns.find(item => item?.type === 'operation') ? colSpan : colSpan + 1
    return pageData.map((source) => {
      /**
        * @description: 主体表格渲染逻辑
        * @param {any} source 主表项
        * @param {number} 主表项索引
        * @return {JSXElement}
      */

      let primaryKey = source[primaryField!];
      let subordinateQuantity: number = SonList[source.id].length;
      let colHide = colHideList[primaryKey];
      let subSource = SonList[source.id]

      return <IntermediateArea
        primaryElevae={primaryElevae}
        colSpan={calcColSpan}
        fixColumns={fixColumns}
        subordinateElevae={subordinateElevae}
        list_columns={list_columns}
        colHide={colHide}
        subordinateQuantity={subordinateQuantity}
        subSource={subSource}
        source={source}
        surfaceItemWidth={surfaceItemWidth}
        trClick={this.handleOpenCol}
      />
    })
  }

  // 加载左固定列
  renderFixLeftTable() {
    const { pageData, selectList, SonList, colHideList, colSpan, subordinateElevae, primaryElevae } = this.state;

    const { primaryField, subSchemaApi } = this.props;

    // 优化：当显隐状态改变时，之前会将所有保存状态的行全部渲染，目前只渲染一个行

    return pageData.map((source) => {
      /**
        * @description: 主体表格渲染逻辑
        * @param {any} source 主表项
        * @param {number} 主表项索引
        * @return {JSXElement}
      */

      let primaryKey = source[primaryField!];
      let subordinateQuantity = SonList![source?.id]?.length;
      let colHide = colHideList[primaryKey];
      let checked = selectList[primaryKey];

      return <LeftArea
        key={source?.id}
        primaryKey={primaryKey}
        subordinateElevae={subordinateElevae}
        primaryElevae={primaryElevae}
        checked={checked}
        subSchemaApi={subSchemaApi}
        subordinateQuantity={subordinateQuantity}
        colHide={colHide}
        trClick={this.handleMasterChange}
      />
    })
  }


  // 加载右固定列
  renderFixRightTable() {
    const { pageData, fixColumns, SonList, colHideList, colSpan, subordinateElevae, primaryElevae } = this.state;

    const { list_columns, primaryField, subSchemaApi } = this.props;

    return pageData.map((source) => {
      /**
        * @description: 主体表格渲染逻辑
        * @param {any} source 主表项
        * @param {number} 主表项索引
        * @return {JSXElement}
      */
      let primaryKey = source[primaryField!];
      let childListLen = SonList[source.id].length;
      let subordOperate = fixColumns[fixColumns?.length - 1];
      let primaryOperate = list_columns[list_columns?.length - 1];
      let colHide = colHideList[primaryKey];
      let childSource = SonList[source.id];

      return <RightArea
        key={source?.id}
        subordinateElevae={subordinateElevae}
        primaryElevae={primaryElevae}
        subSchemaApi={subSchemaApi}
        colSpan={colSpan}
        subordinateQuantity={childListLen}
        colHide={colHide}
        source={source}
        childSource={childSource}
        subordOperate={subordOperate}
        primaryOperate={primaryOperate}
      />
    })
  }


  // 表格主体区域渲染
  renderTableContainer(): JSX.Element {
    const { _container_height } = this.state;
    const { style } = this.props;

    return <div className="lion-table-Content" style={{ ...style, height: _container_height }}>

      {/* 表格及分页渲染区域 */}
      <div className="lion-table-container">
        {/* 表格体渲染区域 */}
        <div className="lion-table-container-body">
          {/* 表格头部及数据渲染区域 */}
          {this.renderTableWrapper()}

          {/* 表格固定列渲染区域 */}
          {this.renderTableFixWrapper()}
        </div>
        {/* 分页渲染区域 */}
        {this.renderPagination()}
      </div>

      {/* loading */}
      <div
        style={{ visibility: this.state.loading ? 'visible' : 'hidden' }}
        className='lion-table-loading'
      >
        <div className='lion-table-loading-wrapper'>
          <Spin tip="Loading..." />
        </div>
      </div>
    </div>
  }

  renderTableWrapper() {
    const { fixColumns, table_height, tableBody, pageData, wrapper, hasFetch } = this.state;
    const { translate, filter } = this.props;
    const existFilter = filter ? true : false;
    {/* 表格头及数据渲染区域 */ }
    return <div className="lion-table-container-body-wrapper">
      <CommonHeader
        fixColumns={fixColumns}
        wrapper={wrapper}
      />
      <div
        ref={tableBody}
        className="lion-table-body"
        style={{ height: !table_height ? '500px' : table_height }}
        // onMouseOut={this.handleTrMouseOut}
        onScroll={this.handleScroll}
      >
        {pageData?.length > 0 ? <table className="lion-table-common-tbody" style={{ width: this.state.wrapper }}>
          <GenericColContainer columns={fixColumns} />
          <tbody className="lion-table-body-tbody">
            {
              this.renderTable()
            }
          </tbody>
        </table> : <EmptyPlaceHolder hasFetch={hasFetch} translate={translate} existFilter={existFilter} />}
      </div>
    </div>
  }

  renderTableFixWrapper() {
    const { table_height, fixColumns, checkAll, colSpan, wrapper } = this.state;
    return (
      <div className="lion-table-container-fixed-wrapper">
        <div
          className="lion-table-container-fixed-wrapper--left"
          style={{
            height: !table_height ? '535px' : (table_height + 35),
            boxShadow: this.state.fixLeft === 0 ? '' : '4px 3px 4px 0 rgb(0 0 0 / 12%)',
            width: this.leftTableWidth
          }}
        >
          <CommonFixHeader
            wrapper={wrapper}
            seat="left"
            fixColumns={fixColumns}
            colSpan={colSpan}
            checkAll={checkAll}
            trClick={this.onCheckAllChange}
          />
          {/* 固定列表格体渲染渲染 */}
          <div
            className="lion-table-container-fixed-body"
            // onMouseOut={this.handleTrMouseOut}
            style={{
              height: !table_height ? '494px' : (table_height - 6)
            }}
          >
            <table className="lion-table-common-tbody" style={{
              width: this.state.wrapper
            }} >
              <GenericColContainer columns={fixColumns} />
              <tbody
                className="lion-table-body-tbody"
              >
                {
                  this.renderFixLeftTable()
                }
              </tbody>
            </table>
          </div>
        </div>
        <div
          className="lion-table-container-fixed-wrapper--right lion-talbe--fix--right--shadow"
          style={{ height: !table_height ? '535px' : (table_height + 35), width: this.rightTableWidth }}
        >
          <CommonFixHeader
            wrapper={wrapper}
            seat="right"
            fixColumns={fixColumns}
            colSpan={colSpan}
          />
          <div
            className="lion-table-container-fixed-body"
            style={{
              height: !table_height ? '494px' : (table_height - 6)
            }}
          // onMouseOut={this.handleTrMouseOut}
          >
            <table className="lion-table-common-tbody" style={{ width: this.state.wrapper }}>
              <GenericColContainer columns={fixColumns} />
              <tbody className="lion-table-body-tbody">
                {
                  this.renderFixRightTable()
                }
              </tbody>
            </table>
          </div>
        </div>
      </div >
    )
  }

  renderPagination() {
    const { perPageAvailable } = this.props;
    const { page, pageSize, totalSize } = this.state;
    return <div className="lion-talbe-container-pagination">
      <div
        className='lion-talbe-container-pagination-wrapper'
      >
        <Pagination
          current={page}
          locale={CN}
          pageSize={pageSize}
          total={totalSize}
          pageSizeOptions={
            perPageAvailable ? perPageAvailable.map(item => String(item)) : ["10", "20", "30", "50"]
          }
          showSizeChanger
          showTotal={this.showTotal}
          onChange={this.handlePageSizeChange}
        />

      </div>
    </div>
  }

  renderUniversalDialog() {
    const { store, render } = this.props;
    return render(
      'dialog',
      {
        ...((store.action as Action) &&
          ((store.action as Action).dialog as object)),
        type: 'dialog'
      },
      {
        key: 'dialog',
        data: store.dialogData,
        // onConfirm: this.handleDialogConfirm.bind(this),
        onClose: this.handleDialogClose.bind(this),
        show: store.dialogOpen
      }
    )
  }

  // shouldComponentUpdate(){

  // }

  componentDidMount() {

    const { page, pageSize } = this.state;
    window.addEventListener('resize', this.MonitorPageChanges);
    window.addEventListener('resize', this.MonitorTableChanges);

    this._uploadRef?.handleBulkChange({ perPage: pageSize, page: page });
    this.initSource({ perPage: pageSize, page: page });

  }

  handleDialogClose(confirmd: any) {
    const { store } = this.props;
    store?.closeDialog(true);
  }

  handleDialogConfirm(
    values: object[],
    action: Action,
    ctx: any,
    components: Array<any>
  ) {
    console.error('暂未支持此方法,请联系开发人员支持');
    return
  }

  componentDidUpdate(prevProp: any, prevState: any) { }

  componentWillUnmount() {
    const scoped = this.context as IScopedContext;
    scoped.unRegisterComponent(this);
    // 将组件从scoped中卸载
    window.removeEventListener('resize', this.MonitorPageChanges);
    window.removeEventListener('resize', this.MonitorTableChanges);
  }



  render() {
    const { env, keepItemSelectionOnPageChange, primaryField, filter } = this.props;
    return (
      <LionTestTableContext.Provider value={{
        env: env,
        handleAction: this.handleAction.bind(this),
        primaryField: primaryField,
        subSchemaApi: this.props.subSchemaApi,
        render: this.props.render,
        subTableTitle: this.props.subTableTitle
      }}>
        <div className="lion-table-Overall-area">
          <LionTableInterrogator filter={filter} _bindRef={this._bindRef} />
          {keepItemSelectionOnPageChange && <SpreadSelection sectionList={this.ids} onChange={this.handleSectionChange} />}
          {this.renderHeaderToolbars()}
          {this.renderTableContainer()}

          {/* Jay 打印标签弹窗 */}
          {this.state.printType && <ModalPrint printType={this.state.printType} {...this.props} {...this.state.ModalProps} filterKey={this.props.filter?.name}
          />}
          {this.renderUniversalDialog()}
        </div>
      </LionTestTableContext.Provider>
    )
  }
}

@Renderer({
  type: 'lion-table',
  storeType: LionTableStore.name
})
export class LionTestTableRenderer extends LionTestTable { }
