import { tableSimple } from '../../configuration/constants'
import { throttle } from '../../utils'
export default {

  // 组件名称
  name: tableSimple,

  // 前面板html模板
  viewTemplate() {
    return `
      <div data-gjs-type="${tableSimple}" class="${tableSimple}">
      </div>
    `
  },
  // 前面板html样式
  viewStyle() {
    return `
      <style>
        .${tableSimple} {
          position: absolute;
          display: flex;
          flex-direction: column;
          width: 500px;
          height: 300px;
          font-size: inherit;
          font-weight: inherit;
          font-style: inherit;
          font-family: inherit;
        }
        .${tableSimple} .table-wrapper {
          display: flex;
          flex-direction: column;
          width: 100%;
          flex: 1 1 auto;
          overflow-x: auto;
        }
        .${tableSimple} .table-body {
          width: 100%;
          flex: 1 1 auto;
          overflow-y: auto;
          overflow-x: hidden;
        }
        .${tableSimple} .table-wrapper::-webkit-scrollbar, .${tableSimple} .table-body::-webkit-scrollbar {
          width: 10px;
          height: 10px;
        }
        .${tableSimple} .table-wrapper::-webkit-scrollbar-thumb, .${tableSimple} .table-body::-webkit-scrollbar-thumb {
          background-color: rgba(110,110,110,.5);
        }
        .${tableSimple} .table-wrapper::-webkit-scrollbar-thumb:hover, .${tableSimple} .table-body::-webkit-scrollbar-thumb:hover {
          background-color: rgba(110,110,110,.3);
        }
        .${tableSimple} .table-wrapper::-webkit-scrollbar-track, .${tableSimple} .table-body::-webkit-scrollbar-track {
          background-color: rgba(110,110,110,.3);
        }
        .${tableSimple} table {
          width: 100%;
          translate: transform 0.4 ease;
          text-align: inherit;
          color: currentColor;
          font-size: inherit;
          font-weight: inherit;
          font-style: inherit;
          font-family: inherit;
        }
        .${tableSimple} table > tbody > tr > td, .${tableSimple} table > thead > tr > th {
          padding: 10px 16px;
          overflow: hidden;
          text-overflow: ellipsis;
          text-align: inherit;
          font-size: inherit;
          font-weight: inherit;
          font-style: inherit;
          font-family: inherit;
        }
        .${tableSimple} table > tbody > tr > td {
          background-position: center center;
          background-size: 100% auto;
          background-repeat: no-repeat;
          word-break: break-all;
          cursor: pointer;
        }
        .${tableSimple} table > tbody > tr:hover > td {
          background-color: rgba(0,0,0,0.06);
        }
        .${tableSimple} table > tbody > tr > td > img {
          max-width: 100%;
        }
        .${tableSimple} .actions {
          margin-bottom: .8em;
          display: flex;
          justify-content: flex-end;
        }
        .${tableSimple} .search {
          border: 1px solid transparent;
          border-radius: 2px;
          position: relative;
        }
        .${tableSimple} .search > input {
          width: 100%;
          height: 30px;
          padding-left: 10px;
          padding-right: 100px;
          border: none;
          background-color: transparent;
          color: inherit;
        }
        .${tableSimple} .search > input:focus {
          outline: none;
        }
        .${tableSimple} .actions button {
          width: 90px;
          padding: 0 16px;
          border: none;
          color: inherit;
          text-align: center;
          cursor: pointer;
          transition: all .3s ease;
        }
        .${tableSimple} .actions .search button {
          position: absolute;
          right: 0;
          top: 0;
          height: 30px;
          border-left: 1px solid transparent;
        }
        .${tableSimple} .actions button:focus {
          outline: none;
        }
        .${tableSimple} .actions button:hover {
          opacity: 0.65;
        }
        .${tableSimple} .actions button > .fa {
          color: inherit;
        }
        .${tableSimple} .actions .btn-download {
          margin-left: .8em;
          height: 32px;
          border-radius: 2px;
        }
        .${tableSimple} .process {
            position: relative;
            display: inline-block;
            vertical-align: middle;
            padding: 28px 0 12px;
            width: 100%;
        }
        .${tableSimple} .process .icon-flag {
            display: none;
        }
        .${tableSimple} .process .process-static {
            width: 100%;
            height: 15px;
            border-radius: 10px;
            box-shadow: inset 0px -5px 10px 0px white;
        }
        .${tableSimple} .process .process-active {
            position: absolute;
            top: 28px;
            left: 0;
            width: 0;
            height: 14px;
            border: 1px solid #4dafe2;
            border-radius: 10px;
            background-size: 5px 5px;
        }
        .${tableSimple} table > thead > tr > th {
          position: relative;
        }
        .${tableSimple} .table-column-sorter {
          position: absolute;
          right: 0;
          top: 0;
          width: 12px;
          height: 100%;
          display: flex;
          flex-direction: column;
          justify-content: center;
          align-items: center;
        }
        .${tableSimple} .table-column-sorter-up {
          margin-bottom: 2px;
          display: inline-block;
          border-style: solid;
          border-width: 6px 4px;
          border-color: transparent transparent #bfbfbf transparent;
        }
        .${tableSimple} .table-column-sorter-down {
          display: inline-block;
          border-style: solid;
          border-width: 6px 4px;
          border-color: #bfbfbf transparent transparent transparent;
        }
        .${tableSimple} .table-column-sorter-up:hover {
          border-bottom-color: currentColor;
        }
        .${tableSimple} .table-column-sorter-down:hover {
          border-top-color: currentColor;
        }
        .${tableSimple} .table-column-sorter-up.active {
          border-bottom-color: #1890ff;
        }
        .${tableSimple} .table-column-sorter-down.active {
          border-top-color: #1890ff;
        }
      </style>
    `
  },

  // 编辑器右侧块管理器中显示属性配置
  blockOptions() {
    return {
      label: "表格",
      attributes: { class: 'fa fa-table' },
    };
  },

  spOptions() {
    return {
      label: '表格',
      icon: 'globe',
      docUrl: 'https://xuelangyun.yuque.com/docs/share/ac79e22a-aca2-4c73-afee-66a15dc0c309?# 《表格》',
      author: '秋水',
      email: 'qiushui.smy@xuelangyun.com',
      inPorts: [
        {
          uuid: 'in1',
          subType: 'json',
          description: {
            zh_CN: '输入Json'
          }
        }],
      outPorts: [
        {
          uuid: 'out1',
          subType: 'json',
          description: {
            zh_CN: '输出选中的Row'
          },
        },
        {
          uuid: 'out2',
          subType: 'all',
          description: {
            zh_CN: '输出高亮的行'
          },
        }
      ]
    }
  },

  // 组件属性
  componentOptions() {
    return {
      droppable: false,
      resizable: true,
      dmode: 'absolute',
      highlightable: false,
      childrenSelectable: false,
      traits: [{
        name: 'showTableTh',
        label: '显示表头',
        changeProp: 1,
        type: 'checkbox'
      }, {
        name: 'theadHeight',
        label: '表头行高(px)',
        changeProp: 1,
        type: 'number',
        min: 0
      }, {
        name: 'thBg',
        label: '表头背景色',
        changeProp: 1,
        type: 'color'
      }, {
        name: 'thColor',
        label: '表头字体颜色',
        changeProp: 1,
        type: 'color'
      }, {
        name: 'thFontSize',
        label: '表头字号',
        changeProp: 1,
        type: 'number'
      }, {
        name: 'thFontWeight',
        label: '表头字体粗细',
        changeProp: 1,
        type: 'number',
        min: 400,
        step: 100,
      }, {
        name: 'thFontItalic',
        label: '表头字体风格',
        changeProp: 1,
        type: 'select',
        options: [{id: 'normal', name: '正常'}, {id: 'italic', name: '倾斜'}]
      }, {
        name: 'evenBgColor',
        label: '偶行背景',
        changeProp: 1,
        type: 'color'
      }, {
        name: 'oddBgColor',
        label: '奇行背景',
        changeProp: 1,
        type: 'color'
      }, {
        name: 'selectedBgColor',
        label: '选中行背景',
        changeProp: 1,
        type: 'color'
      }, {
        name: 'trBorderStyle',
        label: '行边框类型',
        changeProp: 1,
        type: 'select',
        options: [{id: 'none', name: '无边框'}, {id: 'solid', name: '实线'}, {id: 'dashed', name: '虚线'}, {id: 'dotted', name: '点线'}]
      }, {
        name: 'trBorderColor',
        label: '行边框颜色',
        changeProp: 1,
        type: 'color'
      }, {
        name: 'trHeight',
        label: '行高(px)',
        changeProp: 1,
        type: 'number',
        min: 0
      }, {
        name: 'showRowNum',
        label: '显示行数',
        changeProp: 1,
        type: 'checkbox'
      }, {
        name: 'linePeed',
        label: '不换行',
        changeProp: 1,
        type: 'checkbox'
      }, {
        name: 'checkable',
        label: '多选行',
        changeProp: 1,
        type: 'checkbox'
      }, {
        name: 'scrollMore',
        label: '滚动加载',
        changeProp: 1,
        type: 'checkbox'
      }, {
        name: 'trMarginTop',
        label: '行上下间距',
        changeProp: 1,
        type: 'number'
      }, {
        name: 'trMarginLeft',
        label: '单元格左右间距',
        changeProp: 1,
        type: 'number'
      }, {
        name: 'tdWidth',
        label: '固定列宽(px)',
        changeProp: 1,
        type: 'number',
        min: 0
      }, {
        name: 'colWidth',
        label: '列:宽',
        changeProp: 1,
        type: 'key-value',
        width: '25%:75%',
        placeholder: '列索引:宽度'
      }, {
        name: 'colAlign',
        label: '列:对齐',
        changeProp: 1,
        type: 'key-value',
        width: '25%:75%',
        placeholder: '列索引:水平对齐',
        options: [{id: 'left', name: '左侧'}, {id: 'center', name: '居中'}, {id: 'right', name: '右侧'}]
      }, {
        name: 'colImgUrl',
        label: '列:图片',
        changeProp: 1,
        type: 'key-value',
        splitor: '::',
        width: '25%::75%',
        placeholder: '列索引::图片目录url'
      }, {
        name: 'colBgUrl',
        label: '列:背景图',
        changeProp: 1,
        type: 'key-value',
        width: '25%::75%',
        splitor: '::',
        placeholder: '列索引::背景图片'
      }, {
        name: 'colFontsize',
        label: '列:字号',
        changeProp: 1,
        type: 'key-value',
        width: '25%:75%',
      }, {
        name: 'colFontfamily',
        label: '列:字体',
        changeProp: 1,
        type: 'key-value',
        width: '25%:75%',
        options: ['inherit', 'DS-Digital', '庞门正道']
      }, {
        name: 'colStyles',
        label: '自定义列样式',
        changeProp: 1,
        type: 'key-value',
        splitor: '::',
        width: '25%::75%',
        valueType: 'textarea'
      }, {
        name: 'flowUp',
        label: '向上滚动',
        changeProp: 1,
        type: 'checkbox'
      }, {
        name: 'speed',
        label: '滚动速度(s)',
        changeProp: 1,
        type: 'number',
        min: 0,
        step: 0.1
      }, {
        name: 'delay',
        label: '延迟(s)',
        changeProp: 1,
        type: 'number',
        min: 0,
        step: 0.1
      }, {
        name: 'highlight',
        label: '设置高亮',
        changeProp: 1,
        type: 'checkbox'
      }, {
        name: 'highlightLine',
        label: '高亮行',
        type: 'number',
        changeProp: 1,
        min: 1,
        step: 1
      }, {
        name: 'highlightColor',
        label: '高亮字体颜色',
        changeProp: 1,
        type: 'color'
      }, {
        name: 'highlightBackground',
        label: '高亮行背景',
        changeProp: 1,
        type: 'color'
      }, {
        name: 'searchable',
        label: '可搜索',
        changeProp: 1,
        type: 'checkbox'
      }, {
        name: 'downloadable',
        label: '可下载',
        changeProp: 1,
        type: 'checkbox'
      }, {
        name: 'searchWidth',
        label: '搜索框宽度',
        changeProp: 1,
      }, {
        name: 'searchPosition',
        label: '搜索框位置',
        changeProp: 1,
        type: 'select',
        options: [{id: 'flex-start', name: '居左'}, {id: 'center', name: '居中'}, {id: 'flex-end', name: '居右'}]
      }, {
        name: 'no_h_p_cols',
        label: '0水平内边距列',
        changeProp: 1,
      }, {
        name: 'hiddenDimension',
        label: '非渲染数据维度',
        changeProp: 1,
      }, {
        name: 'clickEvent',
        label: '鼠标事件',
        changeProp: 1,
        type: 'select',
        options: [{id: 'null', name: '无'}, {id: 'click', name: '单击'}, {id: 'dblclick', name: '双击'}, {id: 'mousedown', name: '按下'}, {id: 'mouseup', name: '松开'}]
      }, {
        name: 'selectRow',
        label: '行选中方式',
        changeProp: 1,
        type: 'select',
        options: [{id: 'checkbox', name: '多选'}, {id: 'radio', name: '单选'}]
      }, {
        name: 'process',
        label: '替换进度条',
        changeProp: 1,
        type: 'checkbox'
      }, {
        name: 'processColumn',
        label: '列数',
        changeProp: 1,
        type: 'number',
        min: 1,
        step: 1
      }, {
        name: 'processDoneColor',
        label: '已完成颜色',
        changeProp: 1,
        type: 'color',
      }, {
        name: 'processWaitColor',
        label: '待完成颜色',
        changeProp: 1,
        type: 'color',
      }, {
        name: 'processStripeColor',
        label: '条纹颜色',
        changeProp: 1,
        type: 'color',
      }, {
        name: 'columnColor',
        label: '设置列颜色',
        changeProp: 1,
        type: 'checkbox',
      }, {
        name: 'columnColorOrder',
        label: '列数',
        changeProp: 1,
        type: 'number',
        min: 1,
        step: 1
      }, {
        name: 'columnPositiveColor',
        label: '列正值字体颜色',
        changeProp: 1,
        type: 'color',
      }, {
        name: 'columnNegativeColor',
        label: '列负值字体颜色',
        changeProp: 1,
        type: 'color',
      }, {
        name: 'sorts',
        label: '排序列',
        changeProp: 1,
      }, {
        name: 'defaultData',
        changeProp: 1,
        type: 'hide'
      }],
      defaultData:JSON.stringify([
        [
            "ResultStatusTypeID",
            "ResultDateTime",
            "ProgramID",
            "UnitID",
            "PositionID",
            "Length",
            "TorqueMax",
            "AngleMax",
            "STATUS"
        ],
        [
            "0",
            "2022/1/20 7:32:00",
            "23078",
            "136",
            "1",
            "541",
            "110.723",
            "89.73299999999998",
            "1"
        ],
        [
            "0",
            "2022/1/20 7:32:00",
            "23078",
            "136",
            "1",
            "533",
            "111.289",
            "79.365",
            "1"
        ],
        [
            "0",
            "2022/1/20 7:35:00",
            "23078",
            "136",
            "1",
            "526",
            "110.334",
            "81.187",
            "1"
        ],
        [
            "0",
            "2022/1/20 7:36:00",
            "23078",
            "136",
            "1",
            "552",
            "110.48",
            "78.10300000000002",
            "1"
        ],
        [
            "0",
            "2022/1/20 7:37:00",
            "23078",
            "136",
            "1",
            "500",
            "110.221",
            "76.889",
            "1"
        ]
    ]).replace(/\"/g, "\\\""),
      showTableTh: true,
      thBg: "none",
      thColor: "none",
      thFontSize: 14,
      thFontWeight: 400,
      thFontItalic: 'normal',
      evenBgColor: null,
      oddBgColor: null,
      selectedBgColor: '#cce6ff',
      trBorderStyle: 'solid',
      trBorderColor: '#ddd',
      trHeight: 40,
      theadHeight: 40,
      showRowNum: false,
      linePeed: true,
      checkable: false,
      trMarginTop: 0,
      trMarginLeft: 0,
      tdWidth: 0,
      flowUp: false,
      speed: 1,
      delay: 2,
      highlight: false,
      highlightLine: 1,
      highlightColor: null,
      highlightBackground: null,
      searchable: false,
      searchWidth: '100%',
      searchPosition: 'flex-start',
      hiddenDimension: null,
      clickEvent: 'null',
      selectRow: 'checkbox',
      process: false,
      scrollMore: false,
      processColumn: 1,
      processDoneColor: 'rgb(24, 144, 255)',
      processWaitColor: 'rgba(24, 144, 255, 0.3)',
      processStripeColor: 'rgb(77, 175, 226)',
      columnColor: false,
      columnColorOrder: 1,
      columnPositiveColor: 'red',
      columnNegativeColor: 'green',
      sorts: '9,10,11'
    }
  },

  onModelScript() {
    const showTableTh = Boolean('{[ showTableTh ]}');
    const thBg = '{[ thBg ]}';
    const thColor = '{[ thColor ]}';
    const thFontSize = parseInt('{[ thFontSize ]}');
    const evenBgColor = '{[ evenBgColor ]}';
    const oddBgColor = '{[ oddBgColor ]}';
    const selectedBgColor = '{[ selectedBgColor ]}';
    const trBorderStyle = ('{[ trBorderStyle ]}').toString();
    const trBorderColor = ('{[ trBorderColor ]}').toString();
    const thFontItalic = ('{[ thFontItalic ]}').toString();
    const trHeight = Boolean('{[ trHeight ]}') ? parseInt('{[ trHeight ]}') : 0;
    const theadHeight = Boolean('{[ theadHeight ]}') ? parseInt('{[ theadHeight ]}') : 0;
    const thFontWeight = Boolean('{[ thFontWeight ]}') ? parseInt('{[ thFontWeight ]}') : 0;
    const showRowNum = Boolean('{[ showRowNum ]}');
    const linePeed = Boolean('{[ linePeed ]}');
    const checkable = Boolean('{[ checkable ]}');
    const trMarginTop = Boolean('{[ trMarginTop ]}') ? parseInt('{[ trMarginTop ]}') : 0;
    const trMarginLeft = Boolean('{[ trMarginLeft ]}') ? parseInt('{[ trMarginLeft ]}') : 0;
    const speed = Boolean('{[ speed ]}') ? Number('{[ speed ]}') : 0;
    const delay = Boolean('{[ delay ]}') ? Number('{[ delay ]}') : 0;
    const colWidth = ('{[ colWidth ]}').toString();
    const tdWidth = parseInt('{[ tdWidth ]}');
    const colAlign = ('{[ colAlign ]}').toString();
    const flowUp = Boolean('{[ flowUp ]}');
    const highlight = Boolean('{[ highlight ]}');
    const highlightLine = Number('{[ highlightLine ]}');
    const highlightColor = ('{[ highlightColor ]}').toString();
    const highlightBackground = ('{[ highlightBackground ]}').toString();
    const searchable = Boolean('{[ searchable ]}');
    const downloadable = Boolean('{[ downloadable ]}');
    let searchWidth = ('{[ searchWidth ]}').toString();
    const searchPosition = ('{[ searchPosition ]}').toString();
    let searchKey = null;
    const colImgUrl = ('{[ colImgUrl ]}').toString();
    const colBgUrl = ('{[ colBgUrl ]}').toString();
    const colFontsize = ('{[ colFontsize ]}').toString();
    const colFontfamily = ('{[ colFontfamily ]}').toString();
    const colStyles = ('{[ colStyles ]}').toString();
    const no_h_p_cols = ('{[ no_h_p_cols ]}').toString();
    const hiddenDimension = '{[ hiddenDimension ]}';
    const clickEvent = ('{[ clickEvent ]}').toString();
    const selectRow = ('{[ selectRow ]}').toString();
    const process = Boolean('{[ process ]}');
    const scrollMore = Boolean('{[ scrollMore ]}');
    const processColumn = Number('{[ processColumn ]}');
    const processDoneColor = ('{[ processDoneColor ]}').toString();
    const processWaitColor = ('{[ processWaitColor ]}').toString();
    const processStripeColor = ('{[ processStripeColor ]}').toString();
    const columnColor = Boolean('{[ columnColor ]}');
    const columnColorOrder = Number('{[ columnColorOrder ]}');
    const columnPositiveColor = ('{[ columnPositiveColor ]}').toString();
    const columnNegativeColor = ('{[ columnNegativeColor ]}').toString();
    let sorts = "{[ sorts ]}";
    let defaultData = "{[ defaultData ]}";
    const self = this;
    const _id = self.getAttribute('id');
    const eventName = `call-${_id}`;
    let extraIndex;
    let downloadData;

    if (sorts.indexOf(',') > 0) {
      sorts = sorts.split(',').map(item => Number(item));
    } else if (Boolean(sorts)) {
      sorts = [Number(sorts)];
    }

    let extraDimension;
    if (hiddenDimension.indexOf(',') > 0) {
      extraDimension = hiddenDimension.split(',').map(dim => {
        const str = dim.trim();
        if (isNaN(Number(str))) {
          return str;
        } else {
          return parseInt(str);
        }
      });
    } else if (Boolean(hiddenDimension)) {
      extraDimension = [];
      if (isNaN(Number(hiddenDimension))) {
        extraDimension.push(hiddenDimension.toString());
      } else if (Boolean(hiddenDimension)) {
        extraDimension.push(parseInt(hiddenDimension));
      }
    }

    let noHovPaddingCols;
    if (no_h_p_cols.indexOf(',') > 0) {
      noHovPaddingCols = no_h_p_cols.split(',').map(i => parseInt(i));
    } else if (Boolean(no_h_p_cols)) {
      noHovPaddingCols = [parseInt(no_h_p_cols)];
    }

    const setColsKey = function(col, targetObj, splitor, key) {
      const k_v = col.split(splitor);
      const k = k_v[0].trim();
      const v = k_v[1].trim();
      if (!key) {
        targetObj[k] = v;
        return;
      }
      if (!targetObj[k]) {
        targetObj[k] = {};
      }
      targetObj[k][key] = v;
      if (key == 'style') {
        let styles;
        if (v.indexOf(';') > 0) {
          styles = v.split(';')
        } else {
          styles = [v];
        }
        styles.forEach(styleItem => {
          if (styleItem.indexOf(':') > 0) {
            const item = styleItem.split(':');
            const _k = item[0].trim();
            const _v = item[1].trim();
            if (!targetObj[k]) {
              targetObj[k] = {};
            }
            targetObj[k][_k] = _v;
          }
        })
      }
    };

    const getColsProperty = function(targetObj, sourceStr, splitor, key) {
      if (sourceStr.indexOf(',') > 0) {
        sourceStr.split(',').forEach(function(col) {
          setColsKey(col, targetObj, splitor, key);
        });
      } else if (sourceStr.indexOf(splitor) > 0) {
        setColsKey(sourceStr, targetObj, splitor, key);
      }
    };
    const cols = {};
    getColsProperty(cols, colWidth, ':', 'width');
    getColsProperty(cols, colAlign, ':', 'text-align');
    getColsProperty(cols, colBgUrl, '::', 'background-image');
    getColsProperty(cols, colFontsize, ':', 'font-size');
    getColsProperty(cols, colFontfamily, ':', 'font-family');
    getColsProperty(cols, colStyles, '::', 'style');
    getColsProperty(cols, colImgUrl, '::', 'img');
    try {
      defaultData = JSON.parse(defaultData.replace(/\\\"/g, "\""));
      if (downloadable) downloadData = defaultData;
    } catch(err) {
      console.error(defaultData, err)
    }

    if (window.tableTimer && window.tableTimer[_id]) {
      clearInterval(window.tableTimer[_id]);
      window.tableTimer[_id] = undefined;
    } else if (window.tableTimer) {
      Object.keys(window.tableTimer).forEach((timerId) => {
        if (!$('#' + timerId).length) {
          clearInterval(window.tableTimer[timerId]);
          window.tableTimer[timerId] = undefined;
        }
      })
    } else {
      window.tableTimer = {};
    }

    $(self).empty();
    if (searchable || downloadable) {
      const $actions = $('<div class="actions"></div>');
      if (searchable) {
        if (!isNaN(Number(searchWidth))) {
          searchWidth += 'px';
        }
        $actions.append(`
        <div class="search" style="width: ${searchWidth}; align-self: ${searchPosition}; border-color: ${thBg};">
          <input type="text" />
          <button style="background-color: ${thBg}; color: ${thColor};">搜 索</button>
        </div>
      `);
      }
      if (downloadable) {
        $actions.append(`
          <button class="btn-download" style="background-color: ${thBg}; color: ${thColor};">导出</button>
        `);
      }
      $(self).append($actions);
    }
    const $tableWrapper = $('<div class="table-wrapper"></div>')
    $(self).append($tableWrapper)
    if (showTableTh) {
      $tableWrapper.append(`
        <div class="table-head">
          <table style="background-color: ${thBg}; font-size: ${thFontSize}px; font-weight: ${thFontWeight}; font-style: ${thFontItalic}; color: ${thColor};"><thead></thead></table>
        </div>
      `);
    }
    $tableWrapper.append(`
      <div class="table-body" style="overflow-y: ${flowUp ? 'hidden' : 'auto'};">
        <table><thead style="font-size: ${thFontSize}px; visibility: hidden;"></thead><tbody></tbody></table>
      </div>
    `);

    const $tbody = $(self).find('.table-body tbody');
    const $tbody_head = $(self).find('.table-body thead');
    const $thead = $(self).find('.table-head thead');
    const $table = $(self).find('table');
    let marginTop;
    if (!trMarginTop  && !trMarginLeft) {
      $table.css({ 'border-collapse':'collapse', 'border-spacing': '0' });
    } else {
      $table.css({ 'border-collapse':'separate', 'border-spacing': (trMarginLeft || 0) + 'px ' + (trMarginTop || 0) + 'px' });
    }

    const renderHead = function(row) {
      const $tr = $(`
        <tr>
          ${showRowNum ? '<th width="48"></th>' : ''}
          ${checkable ? '<th width="48"><input type="checkbox" name="all" /></th>' : ''}
          <th>${row.join('</th><th>')}</th>
        </tr>
      `);
      if (tdWidth) {
        $tr.children('th').css('width', tdWidth + 'px');
      }
      let startIndex = 0;
      if (showRowNum) startIndex -= 1;
      if (checkable) startIndex -= 1;
      $tr.children('th').each(function(i, el) {
        if (cols[i]) {
          $(el).css('text-align', cols[i]['text-align']);
        }
        if (Boolean(sorts)) {
          const index = i + startIndex;
          const $sort = $(`<div class="table-column-sorter" data-column="${index}"><span class="table-column-sorter-up"></span><span class="table-column-sorter-down"></span></div>`);
          if (sorts.indexOf(index) > -1) {
            $(el).append($sort)
          }
        }
      });
      if (showTableTh) {
        $thead.empty();
        $thead.append($tr.clone());
      }
      $tbody_head.empty();
      $tbody_head.append($tr);
      marginTop = -(trHeight + trMarginTop);
      $tbody_head.parent('table').css('margin-top', marginTop + 'px');
    };

    const renderBodyRow = function(row, index) {
      let data = row;
      if (extraIndex) {
        data = row.filter(function(col, i) {
          return extraIndex.indexOf(i) == -1;
        });
      }
      const $tr = $(`
        <tr>
          ${showRowNum ? '<td width="48">'+ index +'</td>' : ''}
          ${checkable ? '<td width="48"><input type="checkbox" name="all" /></td>' : ''}
          <td>${data && data.join && data.join('</td><td>')}</td>
        </tr>
      `);
      if (tdWidth) {
        $tr.children('td').css('width', tdWidth + 'px');
      }
      $tr.children('td').each(function(i, el) {
        if (cols[i]) {
          for(let prop in cols[i]) {
            if (prop == 'img') continue;
            if (prop == 'background-image') {
              $(el).css(prop, `url(${cols[i][prop]})`);
              continue;
            }
            $(el).css(prop, cols[i][prop]);
          }
        }
        if (cols[i] && cols[i].img) {
          const text = $(el).text();
          $(el).html(`<img src="${cols[i].img}${text}.png" alt="${text}" />`)
        }
        if (noHovPaddingCols && noHovPaddingCols.indexOf(i) > -1) {
          $(el).css({'padding-left': 0, 'padding-right': 0});
        }
      });
      $tr.attr('data-row', JSON.stringify(row));
      if (searchKey && data.join(' ').indexOf(searchKey) == -1) {
        $tr.css('display', 'none')
      }
      if (Boolean(evenBgColor) && index % 2 == 0) {
        $tr.children('td').css("background-color", evenBgColor);
      } else if (Boolean(oddBgColor) && index % 2 == 1) {
        $tr.children('td').css("background-color", oddBgColor);
      }
      if (Boolean(trBorderColor) && index > 0) {
        $tr.css('border-top', `1px ${trBorderStyle || 'solid'} ${trBorderColor}`);
      }
      $tbody.append($tr);
    };

    let tableData = [];
    const renderTable = function(data) {
      $tbody.empty();
      if (tdWidth) {
        $table.width(tdWidth * data[0].length + (showRowNum ? (48 + trMarginLeft) : 0) + (checkable ? (48 + trMarginLeft) : 0) + (trMarginLeft || 0) * (data[0].length + 1));
      }

      tableData = scrollMore ? data.slice(0, tableData.length + 11) : data;
      renderHead(tableData[0]);
      $.each(tableData.slice(1), function(index, row) {
        renderBodyRow(row, index);
      });
      const $td = $(self).find('td');
      const $th = $(self).find('th');
      const $tableBody = $(self).find('.table-body');
      const $tableHead = $(self).find('.table-head');
      if (linePeed) {
      //   $td.css({ 'white-space': 'break-spaces' });
      //   $th.css({ 'white-space': 'break-spaces' });
      //   $table.css({'table-layout': 'auto'});
      // } else {
        $td.css({ 'white-space': 'nowrap' });
        $th.css({ 'white-space': 'nowrap' });
        const tableBodyCssText = $tableBody.attr("style") + ";table-layout: fixed !important;";
        const tableHeadCssText = $tableHead.attr("style") + ";table-layout: fixed !important;";
        $tableBody.css('cssText', tableBodyCssText);
        $tableHead.css('cssText', tableHeadCssText);

      }
      scrollMore && $tableBody.on('scroll', function(e) {
        if ($tableBody[0].scrollTop >= ($tableBody[0].scrollHeight - $tableBody.height())) {
          renderTable(data)
        }
      });
      requestAnimationFrame(resetHeadUi);

      if (trHeight) {
        $td.outerHeight(trHeight)
        $th.outerHeight(trHeight);
      }
      if (theadHeight) {
        $thead.find('th').outerHeight(theadHeight);
      }

      if (flowUp && $tbody.parent().innerHeight() > $tbody.parent().parent().innerHeight()) {
        clearInterval(window.tableTimer[_id]);
        window.tableTimer[_id] = undefined;
        setBodyFlowup()
      } else {
        clearInterval(window.tableTimer[_id]);
        window.tableTimer[_id] = undefined;
      }

      if (process) {
        let backgroundImage = `linear-gradient(-45deg, ${processStripeColor} 0, ${processStripeColor} 25%, transparent 25%, transparent 50%, ${processStripeColor} 50%, ${processStripeColor} 75%, transparent 75%, transparent 100%)`

        $tbody.children('tr').each(function(i, el) {
          let $th = $(el).children('td').eq(processColumn - 1);
          let percent = $th.text();

          if (!isNaN(percent- 0) && (percent- 0) <= 1 && (percent- 0) >= 0 ) {
            percent = (percent- 0) * 100 + '%';
          }

          if (percent.indexOf('%') < 0) {
            return true;
          }

          let progressHtml = `
          <div class="process">
            <i id="icon-flag" class="icon-flag"></i>
            <div class="process-static" style="background-color: ${processWaitColor}"></div>
            <div id="process-bar" class="process-active" style="width: ${percent}; background-image: ${backgroundImage}; background-color: ${processDoneColor} "></div>
          </div>
          `;

          $(el).children('td').eq(processColumn - 1).html(progressHtml);
        });
      }

      if (columnColor) {
        $tbody.children('tr').each(function(e, el) {
          let $td = $(el).children('td').eq(columnColorOrder - 1);
          if (isNaN(Number($td.text()))) {
            return true;
          }

          let color = Number($td.text()) < 0 ? columnNegativeColor : columnPositiveColor;

          $td.css({color: color});
        });
      }

      if (highlight && flowUp && $tbody.parent().innerHeight() <= $tbody.parent().parent().innerHeight()) {
        if (window.tableHighlight) {
          clearInterval(window.tableHighlight[_id]);
          window.tableHighlight[_id] = undefined;
        }

        let $highlightLine = $tbody.children('tr').eq(highlightLine - 1);
        $highlightLine.data({color: $highlightLine.css('color'), 'background-color': $highlightLine.css('background-color') });
        $highlightLine.css({color: highlightColor, 'background-color': highlightBackground });

        window.tableHighlight[_id] = setInterval(function() {
            $tbody.children('tr').each(function(e, el){
              if ($(el).data('color')) {
                $(el).css({color: $(el).data('color'), 'background-color': $(el).data('background-color') });
                $(el).data({color: '', 'background-color': '' });
                let $elNext = $(el).next();
                if ($elNext.length == 0) {
                  $elNext = $tbody.children('tr').first();
                }
                $elNext.data({color: $elNext.css('color'), 'background-color': $elNext.css('background-color') });
                $elNext.css({color: highlightColor, 'background-color': highlightBackground });
                return false;
              }
            });

            let rows = [];
            $highlightLine.children('td').each(function(e, el){ rows.push($(el).text()); })
            sendOut2(rows);
        }, delay * 1000)
      }
    };
    $thead.on('change', 'input[type=checkbox]', function(e) {
      const checked = $(this).is(':checked');
      if (checked) {
        $tbody.find('input[type=checkbox]').attr('checked', true);
      } else {
        $tbody.find('input[type=checkbox]').attr('checked', false);
      }
    })

    const handleColumnSort = function(isUp, colIndex, isActive) {
      const newData = [];
      let column = defaultData.slice(1).map(row => {
        newData.push(row.map(item => item))
        return row[colIndex]
      });
      if (isActive) {      
        $tbody.empty();
        $.each(newData, function(index, row) {
          renderBodyRow(row, index);
        });
        return
      }
      column = _.sortBy(column);
      if (!isUp) column = column.reverse();
      const data = [];
      column.forEach((item, i) => {
        const index = newData.findIndex(row => row[colIndex] === item);
        const row = newData.splice(index, 1)[0];
        data.push(row);
      });
      
      $tbody.empty();
      $.each(data, function(index, row) {
        renderBodyRow(row, index);
      });
    }

    $thead.on('click', '.table-column-sorter', function(e) {
      const $target = $(e.target);
      let columnIndex = $target.parent().attr('data-column');
      let isUp = $target.hasClass('table-column-sorter-up');
      let isActive = $target.hasClass('active');
      if (columnIndex) {
        columnIndex = Number(columnIndex);
      }
      if (isActive) {
        $target.removeClass('active');
      } else {
        $target.addClass('active');
        $target.siblings().removeClass('active')
      }
      handleColumnSort(isUp, columnIndex, isActive)
    })

    const setBodyFlowup = function () {
      const $body = $tbody.parent();
      window.tableTimer[_id] = setInterval(function() {
        const m_t = $tbody.children('tr').first().innerHeight() + trMarginTop - marginTop;

        $body.animate({marginTop: -m_t + 'px'}, speed * 1000,function() {
          if (highlight) {
            let $highlightLine = $tbody.children('tr').eq(highlightLine - 1);

            $tbody.children('tr').each(function(e, el){
              if ($(el).data('color')) {
                $(el).css({color: $(el).data('color'), 'background-color': $(el).data('background-color') });
                $highlightLine.data({color: '', 'background-color': '' });
              }
            });

            $highlightLine.data({color: $highlightLine.css('color'), 'background-color': $highlightLine.css('background-color') });
            $highlightLine.css({color: highlightColor, 'background-color': highlightBackground });

            let rows = [];
            $highlightLine.children('td').each(function(e, el){ rows.push($(el).text()); })
            sendOut2(rows);
          }

          const $first = $tbody.children('tr').first().detach();
          $tbody.append($first);
          $body.css({marginTop: marginTop + 'px'});
        })
      }, delay * 1000)
    };

    const sendOut2 = function (row) {
      window.spSocket && window.spSocket.send({
        eventName: eventName,
        data: {
          success: true,
          out2: JSON.stringify(row)
        }
      });
    };

    const resetHeadUi = function () {
      const $tds = $tbody_head.find('th');
      let width = 0;
      $tds.each(function(i, el) {
        let b_w = $(el).innerWidth();
        let h_w = $thead.find('th').eq(i).innerWidth();
        let w = Math.max(b_w, h_w);
        width += w;
        $(el).innerWidth(w);
        $thead.find('th').eq(i).innerWidth(w);
      });
      $thead.parent('table').innerWidth(width).parent('.table-head').innerWidth(width);
      $tbody.parent('table').innerWidth(width).parent('.table-body').innerWidth(width);
    };

    const handleSearch = function(e) {
      searchKey = $(self).find('.search').children('input').val().trim();
      if (e.type == 'click' || e.keyCode == 13) {
        $(self).find('tbody').children().each(function(i, el) {
          if (searchKey) {
            if($(el).attr('data-row').indexOf(searchKey) < 0) {
              $(el).slideUp('fast')
            } else {
              $(el).slideDown('fast')
            }
          }
        })
      } else if (!searchKey) {
        $(self).find('tbody').children(':hidden').slideDown('fast');
      }
    };

    $(self).find('.search > input').on('keyup', handleSearch)
    $(self).find('.search > button').on('click', handleSearch)

    const handleExtraIndex = function(tableColumn) {
      if (extraDimension && extraDimension.length) {
        extraIndex = extraDimension.map(function(dim, i) {
          if (isNaN(dim)) {
            const index = tableColumn.indexOf(dim);
            if (index == -1) {
              console.log("非渲染数据维度 " + dim + " has not found in data.")
            }
            return tableColumn.indexOf(dim);
          }
          return dim;
        });
      } else {
        extraIndex = null;
      }
    }
    handleExtraIndex(defaultData[0]);
    renderTable(defaultData);

    const handleClickRow = function (e) {
      e.stopPropagation();
      let selectable = !$(this).hasClass('selected');
      if (selectRow == 'radio') {
        $tbody.children().removeClass('selected').css("background-color", "unset");
      }
      if (selectable) {
        $(this).addClass('selected');
        $(this).css("background-color", selectedBgColor);
      } else if (selectRow == 'checkbox') {
        $(this).removeClass('selected');
        $(this).css("background-color", "unset");
      }
      const $selected_trs = $(self).find('tr.selected');
      let rows = [];
      $selected_trs.each(function(i, el) {
        let _row = JSON.parse($(el).attr('data-row'));
        rows.push(_row);
      });
      window.spSocket && window.spSocket.send({
        eventName: eventName,
        data: {
          success: true,
          out1: JSON.stringify(rows)
        }
      });
    };
    const sendCheckedRow = function(param) {
      const checkedRows = [];
      $tbody.find('input[type=checkbox]:checked').each(function(i, el) {
        const data = $(el).parents('tr').attr("data-row");
        checkedRows.push(JSON.parse(data));
      });
      const outData = {type: param, data: checkedRows};
      window.spSocket && window.spSocket.send({
        eventName: eventName,
        data: {
          success: true,
          out1: JSON.stringify(outData)
        }
      });
    }

    if (window.prevEventType && window.prevEventType[eventName]) {
      $(self).off(window.prevEventType[eventName], 'table > tbody > tr');
    }
    if (clickEvent !== 'null' && !checkable) {
      $(self).on(clickEvent, 'table > tbody > tr', handleClickRow);
      if (!window.prevEventType) {
        window.prevEventType = {};
      }
      window.prevEventType[eventName] = clickEvent;
    }

    $(self).on('click', '.btn-download', function() {
      if (downloadData) {
        const csvStr = Papa.unparse(downloadData, {
          skipEmptyLines: true,
        });
        let link = document.createElement('a')
        let body = document.querySelector('body')
        link.href = window.URL.createObjectURL(new Blob(["\ufeff" + csvStr], { type: 'text/csv;charset=utf-8;' }))
        link.download = '表格数据.csv'

        link.style.display = 'none'
        body.appendChild(link)

        link.click()
        body.removeChild(link)

        window.URL.revokeObjectURL(link.href);
        link = undefined;
      }
    })

    window.ee && window.ee.on('table-' + _id, function(param) {
      sendCheckedRow(param);
    });

    if (window.spSocket) {
      window.spSocket.subscribe({
        eventName: eventName,
        callback: function (_data) {
          if (_data.data.in1) {
            let data = JSON.parse(_data.data.in1);
            if (downloadable) {
              downloadData = data;
            }
            if (Boolean(sorts)) {
              defaultData = data;
            }
            handleExtraIndex(data[0]);
            renderTable(data);
          }
        }
      });
    }
  },

  onViewInit() {
    const evn = `
      change:showTableTh
      change:thBg
      change:thColor
      change:thFontSize
      change:evenBgColor
      change:oddBgColor
      change:selectedBgColor
      change:trBorderStyle
      change:trBorderColor
      change:theadHeight
      change:thFontItalic
      change:thFontWeight
      change:trHeight
      change:colWidth
      change:colAlign
      change:showRowNum
      change:linePeed
      change:checkable
      change:trMarginTop
      change:trMarginLeft
      change:tdWidth
      change:flowUp
      change:speed
      change:delay
      change:highlight
      change:highlightLine
      change:highlightColor
      change:highlightBackground
      change:searchable
      change:searchWidth
      change:searchPosition
      change:colImgUrl
      change:colBgUrl
      change:colFontsize
      change:colFontfamily
      change:colStyles
      change:no_h_p_cols
      change:hiddenDimension
      change:clickEvent
      change:scrollMore
      change:process
      change:processColumn
      change:processDoneColor
      change:processWaitColor
      change:processStripeColor
      change:columnColor
      change:columnColorOrder
      change:columnPositiveColor
      change:columnNegativeColor
      change:downloadable
      change:selectRow
      change:sorts
    `;
    this.listenTo(this.model, evn, this.updateScript);
    this.listenTo(this.model, evn, this.em.handleUpdates.bind(this.em));
    this.listenTo(this.em, 'update:component:style:height update:component:style:width', throttle.bind(this, this.updateScript.bind(this)));
  }
}
