<template>
  <div>
    <vxe-grid
      ref="xTable"
      :resizable="(resizable === undefined || resizable === true)?true:false"
      :column-key="tableName!==undefined?true:false"
      :highlight-current-row="
      hideCheckbox!==undefined|| hideCheckbox === true"
      :height="newTableHeight"
      :loading="loading"
      :auto-resize="true"
      :scroll-y="setOptimization === undefined?defOptimization:setOptimization"
      :scroll-x="setXOptimization === undefined?defXOptimization:setXOptimization"
      size="mini"
      :checkbox-config="selectConfig"
      border
      @checkbox-all="_selectAll"
      stripe
      @checkbox-change="_selectRowChange"
      show-overflow
      @cell-click="_cellChange"
      show-header-overflow
      @cell-dblclick="_dbChange"
      @radio-change="_radioChange"
      :cell-class-name="_tableCellClassName"
      :row-class-name="_tableRowClassName"
      :edit-config="isEdit !== undefined?editConfig:null"
      :radio-config="isRadio !== undefined?radioConfig:null"
      :row-key="true"
      :tooltip-config="{enterable:true}"
      :animat="false"
      @scroll="_scroll"
    >
      <vxe-table-column
        v-if="hideCheckbox===undefined || hideCheckbox === false"
        type="checkbox"
        fixed="left"
        width="50"
        align="center"/>
      <vxe-table-column
        v-if="isRadio === true"
        type="radio"
        title="单选"
        fixed="left"
        align="center"
        width="50"/>
      <vxe-table-column
        v-if="!isNoOrder"
        type="seq"
        fixed="left"
        title="序号"
        width="50"
        align="center"/>
      <slot></slot>
      <vxe-table-column
        :width="$optColWidth(iconMsg)"
        v-if="$optColWidth(iconMsg)>0?true:false"
        title="操作"
        align="center" fixed="right">
        <template slot-scope="scope">
          <VXEIconList :msg="iconMsg" @on-result-change="_iconClick" :rowData="scope.row"
                       :rowIndex="scope.rowIndex"></VXEIconList>
        </template>
      </vxe-table-column>
      <slot name="col"></slot>
      <!--自定义插槽 pager 插槽-->
      <template v-slot:pager>
        <vxe-pager
          v-if="hidePage === undefined"
          :current-page="getPage.current"
          :page-size="getPage.size"
          :total="getPage.total"
          :pageSizes="pageSizeOpts"
          :background="true"
          @page-change="_pageSizeChange">
          <template v-slot:left>
            <i @click="_refreshPage" class="el-icon-refresh page-refresh"></i>
          </template>
        </vxe-pager>
      </template>
    </vxe-grid>
    <!--自定义表格列-->
    <div style="position: absolute;right:0;top:0;z-index:2000">
      <slot name="setting"></slot>
    </div>
  </div>
</template>

<script>
/**
 * VXE-TABLE 通用 (单选，多选，双击，自定义操作列，自定义表格列)
 * 临时使用，后期删除
 * 最新的table
 */
import VXEIconList from '../base/VXEIconList'

export default {
  name: 'PTVXETable',
  components: { VXEIconList },
  props: {
    tableHeight: null,
    getPage: null,
    hidePage: null,
    clickValue: null,
    selectData: null,
    hideCheckbox: null,
    isReport: null, // 判断是否是报告
    isDataInput: null, // 判断数据录入
    isTask: null, // 判断是否是检测管理
    isHandle: null, // 样品
    tableName: null, // 该值存在，则支持自定义表格
    iconMsg: null,
    pageColumns: null,
    isEdit: null, // 是否可编辑
    setOptimization: null, // 加载滚动配置项
    setXOptimization: null, // 加载滚动配置项(横向)
    isRadio: null, // 是否是单选
    isGC: null, // 国抽（抽样单管理）
    isGroup: null, // 科室为化验室单元格变红色
    isNoOrder: null, // 如果是true的话，则不显示序号这一列
    pageSize: null,
    rows: null,
    resizable: null // 是否允许列拖动
  },
  data() {
    return {
      formId: '',
      extendsData: {},
      loading: false,
      pageParams: {
        page: 1,
        rows: this.rows !== undefined ? this.rows : this.$defRow
      },
      rowData: {},
      checkData: [], // 用于多选的高亮显示数据
      sampleHandleValue: '',
      // 一系列配置
      pageSizeOpts:
        this.pageSize !== undefined ? this.pageSize : [50, 100, 500, 1000],
      // 默认的配置
      defOptimization: this.$setYOptimization,
      defXOptimization: this.$setXOptimization,
      selectConfig: { checkField: 'checked', trigger: 'row' },
      editConfig: {
        trigger: 'click',
        mode: 'cell',
        showIcon: true,
        autoClear: false,
        showStatus: true
      },
      // 单选的配置项
      radioConfig: { trigger: 'row' },
      tableColCount: 0, // 执行的次数
      scrollLeft: 0
    }
  },
  computed: {
    // 表格需要重新计算高度
    newTableHeight: function() {
      const newVal = this.tableHeight
      if (typeof newVal === 'number' && this.hidePage === undefined) {
        // 是数值,并且有分页的时候
        return newVal - 35
      } else {
        // 非数值，不变
        return newVal
      }
    }
  },
  watch: {
    // 监听数据
    'getPage.records': function(newVal, oldVal) {
      this._loadData(newVal)
    }
  },
  methods: {
    // 滚动条位置
    _scroll(data) {
      this.scrollLeft = data.scrollLeft
    },
    _loadData(data) {
      // 阻断 vue 对大数组的双向绑定，大数据性能翻倍提升
      if (this.$refs.xTable) {
        this.$refs.xTable.loadData(data)
      }
    },
    // 更新滚动条状态
    _updateScroll() {
      // 纵向滚动条滚动到顶部，否则会出现固定列空白的情况
      this.$refs.xTable.scrollTo(this.scrollLeft ? this.scrollLeft : 1, 1)
    },
    // 刷新column 和刷新数据
    _refreshColumn() {
      this.$refs.xTable.refreshColumn()
      this.$refs.xTable.syncData()
      // 滚动条错位、固定列不同步
      this.$refs.xTable.refreshScroll()
    },
    // 重置column（使用此方法，重新渲染表格列，将会降低性能）
    _loadColumn(userColumns) {
      this.$nextTick(() => {
        const xTable = this.$refs.xTable
        // eslint-disable-next-line no-unused-vars
        const { fullColumn, tableColumn } = xTable.getTableColumn()
        // 1)取列的头和尾，用于最后进行拼接
        const fullColumnHeader = [] // 头+操作
        const fullColumnOther = [] // 除了头和尾的其他部分
        for (let i = 0; i < fullColumn.length; i++) {
          if (fullColumn[i].property === undefined) {
            // 前几列（checkbox,radio,序号，操作等）
            fullColumnHeader.push(fullColumn[i])
          }
        }
        // 2)根据userColumns 更换列顺序
        for (let i = 0; i < userColumns.length; i++) {
          const itemObj = this.$searchObjByKey(
            userColumns[i].key,
            fullColumn,
            'property'
          )
          if (itemObj) {
            fullColumnOther.push(itemObj)
          }
        }
        // 3)三个数组进行拼接
        const fullColumnTemp = [...fullColumnHeader, ...fullColumnOther]
        // 4)重载表格列
        xTable.loadColumn(fullColumnTemp)
      })
    },
    _clearSelection() {
      this.$nextTick(function() {
        this.$refs.xTable.clearCheckboxRow()
      })
      this.checkData = []
      if (this.hideCheckbox === undefined || this.hideCheckbox === false) {
        if (this.selectData === undefined) {
          this.$emit('on-result-change', 'selectIds', [])
        } else {
          this.$emit('on-result-change', 'selectData', [])
        }
      }
    },
    _checkAll() {
      setTimeout(() => {
        // 控制checkbox状态（加0s的延时才好用）
        this.$refs.xTable.setAllCheckboxRow(true)
        // 全选当前界面的数据
        this._selectRowChange({ selection: this.getPage.records })
      }, 0)
    },
    _pageSizeChange(row) {
      switch (row.type) {
        case 'size':
          this.pageParams.page = 1
          this.pageParams.rows = row.pageSize
          this._pageParamsChange()
          break
        case 'current':
          this._pageChange(row.currentPage)
          break
      }
    },
    // 底部刷新page
    _refreshPage() {
      this._pageParamsChange()
    },
    _pageChange(page) {
      this.pageParams.page = page
      this._pageParamsChange()
    },
    _pageParamsChange() {
      this.$emit('on-result-change', 'changeSize')
    },
    _searchParams() {
      const data = {}
      const serData = this.$serialize(this.formId)
      Object.assign(data, serData, this.extendsData)
      if (this.hidePage === undefined) {
        return this.$extend(data, this.pageParams)
      } else {
        return this.$extend(data)
      }
    },
    _page(formId, uri, extendsData) {
      this.loading = true
      if (this.tableName && this.tableColCount === 0) {
        // tableName存在-----支持自定义表格，只执行一次
        this._settingCol(formId, uri, extendsData)
        this.tableColCount = this.tableColCount + 1 // 递增1
      } else {
        this._pageTemp(formId, uri, extendsData)
      }
    },
    // 根据tableName 获取 column
    _getColByTableName() {
      this._settingCol('', '/', '', { col: true })
    },
    // param 为临时参数，不请求接口，但是需要返回column用
    _settingCol(formId, uri, extendsData, param) {
      if (uri) {
        // 为了避免uri为undefined
        this.$store
          .dispatch('SysTableColumn/getByTableName', this.tableName)
          .then(() => {
            // 查询用户下的表格数据
            const userTableCode = this.$store.state.SysTableColumn.model
            let userColumns = this.pageColumns // 默认值
            // 自定义列接口报错，不能影响其他的接口
            if (userTableCode !== undefined) {
              userColumns = this.$tableColumns(this.pageColumns, userTableCode)
            }
            this.$emit('on-result-change', 'table-col', userColumns)
            // 重置表格列顺序
            this._loadColumn(userColumns)
            if (!param) {
              this._pageTemp(formId, uri, extendsData)
            }
          })
      }
    },
    // 临时
    _pageTemp(formId, uri, extendsData) {
      this.formId = formId
      if (extendsData) {
        this.extendsData = extendsData
      }
      this._requestPage(uri, this._searchParams())
    },
    // 重新请求page接口
    _requestPage(uri, params) {
      this.$store.dispatch(uri, params).then(() => {
        this.loading = false
        this.$emit('on-result-change', 'page', '')
        this._refreshColumn()
        // 每次请求完清空上次的选择
        this._clearSelection()
        // 更新滚动条的状态
        this._updateScroll()
      })
    },
    // 多选
    _selectAll: function(data) {
      this._selectRowChange(data)
    },
    _selectRowChange(data) {
      if (this.hideCheckbox === undefined || this.hideCheckbox === false) {
        const selData = data.selection
        this.checkData = selData
        // 默认返回的是id数组
        if (this.selectData === undefined) {
          const idList = []
          for (let i = 0; i < selData.length; i++) {
            idList.push(selData[i].id)
          }
          this.$emit('on-result-change', 'selectIds', idList)
        } else {
          // 有selectData参数时执行
          this.$emit('on-result-change', 'selectData', selData)
        }
      }
    },
    // 整行变色
    _tableRowClassName({ row, rowIndex }) {
      if (this.checkData.length !== 0) {
        /* 选中的进行高亮显示 */
        const index = this.checkData.indexOf(row)
        if (index !== -1) {
          return 'high-light-row'
        }
      } else {
        /* 没选中的根据页面逻辑变色 */
        // eslint-disable-next-line no-lonely-if
        if (this.isHandle !== undefined && row.endDate) {
          // 样品待处理界面
          if (this.$warningValue(row.endDate) <= 0) {
            return 'warning-row' // 红色
          } else if (
            this.$warningValue(row.endDate) > 0 &&
            this.$warningValue(row.endDate) <= this.sampleHandleValue
          ) {
            return 'warn-row' // 橙色
          }
        }
      }
    },
    // 单元格变色
    _tableCellClassName({ row, rowIndex, column, columnIndex }) {
      if (this.isReport !== undefined) {
        // 报告管理
        if (
          column.property === 'sampleProgress' &&
          row.sampleProgress &&
          row.sampleProgress.indexOf('退回') !== -1
        ) {
          // 含有退回就变红
          return 'cell-red'
        }
        if (
          column.property === 'progress' &&
          row.progress &&
          row.progress.indexOf('退回') !== -1
        ) {
          // 含有退回就变红
          return 'cell-red'
        }
        // 是否合格字体变色
        if (
          column.property === 'isEligible' &&
          row.isEligible &&
          row.isEligible === '合格'
        ) {
          return 'cell-blue-color'
        } else if (
          column.property === 'isEligible' &&
          row.isEligible &&
          row.isEligible === '不合格'
        ) {
          return 'cell-red-color'
        }
      } else if (this.isDataInput !== undefined) {
        if (
          column.property === 'name' &&
          row.progress &&
          row.progress.display.indexOf('退回') !== -1
        ) {
          // 含有退回就变红
          return 'cell-red'
        }
      } else if (this.isTask !== undefined) {
        if (
          column.property === 'serviceType' &&
          row.serviceType &&
          row.serviceType.indexOf('加急') !== -1
        ) {
          return 'cell-red'
        }
      } else if (this.isGC !== undefined) {
        // 国抽的抽样单管理
        if (
          column.property === 'samplingNum' &&
          row.unsuccessfulCount &&
          row.unsuccessfulCount > 0
        ) {
          // 国抽对接未成功项目数量(抽样单编号变红)
          return 'cell-red'
        }
      } else if (this.isGroup !== undefined) {
        if (column.property === 'groupName' && row.groupName === '化验室') {
          // 国抽的检测项目列表，科室为化验室(变红)
          return 'cell-red'
        }
      } else {
        // 其他列表状态
        // eslint-disable-next-line no-lonely-if
        if (column.property === 'progress') {
          if (undefined === row.progress) {
            return 'cell-blue-color'
          } else if (
            undefined !== row.progress &&
            undefined !== row.progress.display
          ) {
            if (row.progress.display.indexOf('退回') !== -1) {
              return 'cell-red-color'
            } else {
              return 'cell-blue-color'
            }
          } else if (undefined !== row.progress) {
            if (row.progress.indexOf('退回') !== -1) {
              return 'cell-red-color'
            } else {
              return 'cell-blue-color'
            }
          } else {
            return 'cell-blue-color'
          }
        } else if (column.property === 'status') {
          if (
            row.status &&
            row.status.display !== undefined &&
            row.status.display.indexOf('退回') !== -1
          ) {
            return 'cell-red-color'
          } else {
            return 'cell-blue-color'
          }
        }
      }
    },
    // 操作列回调
    _iconClick(name, rowData, componentName, rowIndex, obj) {
      this.$emit('on-result-change', 'iconClick', {
        name: name,
        rowData: rowData,
        componentName: componentName,
        rowIndex: rowIndex,
        obj: obj
      })
    },
    // 双击行操作
    _dbChange(data, event) {
      this.$emit('on-result-change', 'dbSelect', data.row)
    },
    // 点击单元格触发
    _cellChange(data, event) {
      if (this.clickValue !== undefined) {
        // 有clickValue参数时执行
        this.$emit('on-result-change', 'singleSelect', data.row)
      }
    },
    // 单选操作
    _radioChange({ row }) {
      this.checkData = [row]
      this.$emit('on-result-change', 'singleSelect', row)
    },
    // 关闭loading
    _hideLoading() {
      this.loading = false
    },
    // 打开loading
    _showLoading() {
      this.loading = true
    },
    // 只刷新选中行的数据
    _refreshRows(rowList, scroll) {
      const records = this.getPage.records
      for (let i = 0; i < rowList.length; i++) {
        const index = records.findIndex(item => item.id === rowList[i].id)
        if (index !== -1) {
          this.$set(this.getPage.records, index, rowList[i])
        }
      }
      this._clearSelection()
      if (!scroll) {
        // 滚动到指定行
        this.$refs.xTable.scrollToRow(rowList[0])
      }
    },
    // 公共方法：更新选中的数据 url:请求地址, params:参数
    // noScroll：true ,没有操作列的不需要更新table的滚动条,或者说没有横向滚动条
    _updateRows(obj) {
      this._showLoading()
      const params = { page: 1, rows: this.$updateRows } // 暂定
      Object.assign(params, obj.params)
      const store = obj.url.split('/')[0] // 注意接口中不要有/的情况
      this.$store.dispatch(obj.url, params).then(() => {
        const result = this.$store.state[store].page.records
        if (result && result.length) {
          this._refreshRows(result, obj.noScroll)
          this._hideLoading()
        } else {
          delete params.ids // 重新请求的时候删除ids
          // 根据查询条件没有搜索到值，则重新根据查询条件请求page接口
          this._requestPage(obj.url, params)
        }
      })
    },
    // 设置单选选中行数据
    _setRadioRow(data) {
      this.$refs.xTable.setRadioRow(data)
      this.checkData = [data]
    }
  }
}
</script>
