<template>
  <div>
  <!-- v-bind:表格属性 v-on:表格事件监听 data:表格数据-->
  <el-table
  :height="tableHeight"
  v-bind="tablePropertites"
  v-on="$listeners"
  :data="data">
    <template v-for="tp in columnTypes">
      <!--如果列类型为expand，处理展开显示数据 -->
      <el-table-column v-if="tp === 'expand'" type="expand" :key="tp">
        <template slot-scope="props">
          <slot name="expand" v-bind="props"></slot>
        </template>
      </el-table-column>
      <!--否则为序号或复选框，直接设置类型即可 -->
      <el-table-column v-else :type="tp" :key="tp"></el-table-column>
    </template>
    <!-- renderColumns:列数组 v-bind="getColBind(col)":获取每列的属性  -->
    <template v-for="col in renderColumns" >
    <el-table-column v-if="col.columnsProps.type!=='text'"
       :key="col.label" v-bind="getColBind(col)">
      <template scope="scope">
        <component :is="col.component"
          v-bind="getCptBind(scope, col)"
          v-on="col.listeners">
        </component>
      </template>
    </el-table-column>
    <el-table-column v-else v-bind="getColBind(col)"></el-table-column>
    </template>
  </el-table>
  <div class="footer">
    <!-- <div class="export-footer">
      <el-button icon="upload2" size="small">导出</el-button>
      <el-select v-model="exportType" size="small" style="width:125px;">
        <el-option
          v-for="item in exportOptions"
          :key="item.value"
          :label="item.label"
          :value="item.value">
        </el-option>
      </el-select>
    </div> -->
    <div class="pagination-footer"> 
        <!-- <span style="padding-top:10px"><el-button v-show="isExport" @click="export2Excel">导出</el-button></span> -->
        <span class="description">{{description}}</span>
        <el-pagination
          v-show="hasPagination"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="currentPage"
          :page-sizes="pageSizes"
          :page-size="tpageSize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="totalCount">
        </el-pagination>
      </div>
    </div>
  </div>
</template>

<script>
import methods from './methods'
import Text from './text'
import Button from './tableComponents/tableButton'
import Input from './tableComponents/tableInput'
import Select from './tableComponents/tableSelect'
import NumberInput from './tableComponents/tableNumberInput'
import Switch from './tableComponents/tableSwitch'
import Icon from './tableComponents/tableIcon'
import Checkbox from './tableComponents/tableCheckbox'
import Datepicker from './tableComponents/tableDatetime'
const BOOLEAN_KEYS = [             // 表格中值为boolean的属性
  'fit',
  'stripe',
  'border',
  'show-header',
  'highlight-current-row',
  'default-expand-all',
  'show-summary'
]

const COLUMN_PROPS = {             // 默认列属性
  align: 'left',
  component: Text
}

const TYPES = ['selection', 'expand', 'index']  // 表格类型[selection：复选框；expand：展开表格；index：序号]

const COLUMN_KEY_MAP = {          // table-column 中 label 和 prop 对应的值
  label: 'label',
  prop: 'prop'
}

const tableComponents = {
  'text': Text,
  'button': Button,
  'input': Input,
  'select': Select,
  'number': NumberInput,
  'switch': Switch,
  'icon': Icon,
  'checkbox': Checkbox,
  'date': Datepicker
}

export default {
  mixins: [methods],
  props: {
    data: {                             // 表格数据
      type: Array,
      default: []
    },
    columns: {                          // 表格数据
      type: Array,
      default: []
    },
    columnType: [String, Array],        // 列类型[序号、复选框、展开]

    columnKeyMap: Object,

    columnsSchema: Object,

    columnsHandler: Function,

    slotAppend: Boolean,

    hasPagination: Boolean, // 是否显示分页条

    totalCount: Number,  // 表格数据总数

    pageSizes: {    // 决定每页显示的条数[10,15,20,25]
      type: Array,
      default: function () {
        return [5, 10, 20, 50]
      }
    },

    description: { // 分页脚底左侧的数据说明
      type: String,
      default: ''
    },

    pageSize: { // 每页条数
      type: Number,
      default: 5
    },

    currentPage: { // 当前页码
      type: Number,
      default: 1
    },

    setPage: Function
  },
  methods: {
    // 删除列属性中无效值
    getColBind (col) {
      const bind = Object.assign({}, col)
      delete bind.component
      delete bind.listeners
      delete bind.propsHandler
      return bind
    },
    // 获取组件属性
    getCptBind (scope, col) {
      const {row, column} = scope
      const index = scope.$index
      const props = { row, col, column, index, 'data': this.data }
      const handler = col.propsHandler
      return handler && handler(props) || props
    },
    handleSizeChange: function (size) {
      this.tpageSize = size
      this.$parent.currentPage = 1
      this.setPage(1, this.tpageSize)
    },
    handleCurrentChange: function (currentPage) {
      this.$parent.currentPage = currentPage
      this.setPage(currentPage, this.tpageSize)
    },
    exportExcel (exportData) {
      return this.export2Excel(exportData)
    },
    export2Excel (exportData) {
      require.ensure([], () => {
        const { export_json_to_excel } = require('@/utils/Export2Excel')
        const tHeader = this.columns.map(item => item.label)
        const filterVal = this.columns.map(item => item.prop)
        const list = exportData
        const data = this.formatJson(filterVal, list)
        export_json_to_excel(tHeader, data, '导出excel')
      })
    },
    formatJson (filterVal, jsonData) {
      return jsonData.map(v => filterVal.map(j => v[j]))
    }
  },
  watch: {
  },
  mounted () {
    if (document.body.scrollHeight < 500) {
      this.tableHeight = 500
    } else {
      if (document.body.scrollHeight > 1000) {
        this.tableHeight = 750
      } else {
        this.tableHeight = document.body.scrollHeight - 250
      }
    }
    window.onresize = function () {
      if (document.body.scrollHeight < 500) {
        this.tableHeight = 500
      } else {
        this.tableHeight = document.body.scrollHeight - 250
      }
    }
  },
  data () {
    return {
      hasFindFocusCpt: false,
      tableHeight: 0,
      tpageSize: this.pageSize,
      exportType: 'selectedData',
      exportOptions: [
        {
          label: '导出选中项',
          value: 'selectedData'
        },
        {
          label: '导出当前页',
          value: 'currentPage'
        },
        {
          label: '导出所有数据',
          value: 'allData'
        }
      ]
    }
  },
  computed: {
    // 处理 $attrs 里面 Boolean 类型的 prop 和统一 prop 命名
    tablePropertites () {
      // 取得table标签下的属性
      const { $attrs } = this
      const properties = {}
      Object.keys($attrs).forEach(key => {
        const v = $attrs[key]
        // 正则表达式，将属性中大写字母替换为-字母，并全部转小写，如maxHeight,转换后得到max-heigth
        const uniformKey = key.replace(/([A-Z])/, '-$1').toLowerCase()
        // 如果属性没有值，并且该属性在boolean值属性列表中，那么给该属性赋值true，否则保持不变
        // ~按位取反运算符--二进制
        // 取反目的，只要结果不为0就是true,代表属性列表中有该属性
        properties[key] = ~BOOLEAN_KEYS.indexOf(uniformKey) && v === '' ? true : v
      })
      return properties
    },
    // 列组装方法
    renderColumns () {
      const {
        columns, // 列值
        columnKeyMap, // 列中label与prop对应的值
        columnsHandler,
        columnsSchema: schema
      } = this
      // 自定义列keyMap和默认keyMap合并
      const map = Object.assign({}, COLUMN_KEY_MAP, columnKeyMap)
      // 循环列，将列的各个属性合并
      const renderColumns = columns.map(col => {
        const props = col.columnsProps // 列的属性
        const componentProperties = col.componentProperties // 组件属性
        if (!this.hasFindFocusCpt) {
          var cptType = (!props.type ? 'text' : props.type)
          if (cptType === 'input') {
            this.$set(col, 'isFocus', true)
            this.hasFindFocusCpt = true
          }
        }
        const componentType = !props.type ? 'text' : props.type
        this.$set(props, 'component', tableComponents[componentType])
        this.$set(props, 'type', componentType)
        // 获取自定义列的样式属性
        const mix = schema && schema[col[map.label]] || {}
        // 将列的值、列的默认属性、列的传入属性、自定义列属性合并
        const it = Object.assign({}, COLUMN_PROPS, props, col, mix, componentProperties)
        it.label = it[map.label]
        it.prop = it[map.prop]
        return it
      })
      return columnsHandler && columnsHandler(renderColumns) || renderColumns
    },
    // 列类型格式化方法
    columnTypes () { // 获取列类型
      const { columnType: type } = this
      if (!type) return [] // 如果没有设置返回空
      // 如果列类型是String类型，并且存在于列类型数组中，直接返回值
      if (typeof type === 'string' && ~TYPES.indexOf(type)) {
        return [type]
      }
      // 如果是数组类型，并且每个值都存在于列类型数组中，返回
      return Array.isArray(type) && type.filter(it => ~TYPES.indexOf(it)) || []
    }
  }
}
</script>

<style>
.footer {
    background: #eef1f6;
    width: 100%;
    height: 40px;
  }
.export-footer {
    float:left;
    margin-top:5px;
    margin-left: 45px;
    margin-bottom:5px;
  }
.pagination-footer .description{
    float:left;
    margin-left:20px;
    margin-top:12px;
  }
  .pagination-footer .el-pagination{
    float:right;
    margin-top:5px;
    margin-bottom:5px;

  }
</style>
