<template>
  <div class="table-container">
    <el-table
      :data="data"
      :border="setBorder"
      v-bind="$attrs"
      row-key="id"
      stripe
      style="width: 100%"
      v-loading="config.loading"
      @selection-change="onSelectionChange"
    >
      <el-table-column type="selection" :reserve-selection="true" width="30" v-if="config.isSelection" />
      <el-table-column type="index" label="序号" width="60" v-if="config.isSerialNo" />
      <el-table-column
        v-for="(item, index) in setHeader"
        :key="index"
        show-overflow-tooltip
        :prop="item.key"
        :width="item.colWidth"
        :label="item.title"
      >
        <template v-slot="scope">
          <template v-if="item.type === 'image'">
            <el-image
              :style="{ width: `${item.width}px`, height: `${item.height}px` }"
              :src="scope.row[item.key]"
              :zoom-rate="1.2"
              :preview-src-list="[scope.row[item.key]]"
              preview-teleported
              fit="cover"
            />
          </template>
          <template v-else>
            {{ scope.row[item.key] }}
          </template>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="100" v-if="config.isOperate">
        <template v-slot="scope">
          <el-popconfirm title="确定删除吗？" @confirm="onDelRow(scope.row)">
            <template #reference>
              <el-button text type="primary">删除</el-button>
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
      <template #empty>
        <el-empty description="暂无数据" />
      </template>
    </el-table>
    <div class="table-footer mt15">
      <el-pagination
        v-model:current-page="state.page.pageNum"
        v-model:page-size="state.page.pageSize"
        :pager-count="5"
        :page-sizes="[10, 20, 30]"
        :total="config.total"
        layout="total, sizes, prev, pager, next, jumper"
        background
        @size-change="onHandleSizeChange"
        @current-change="onHandleCurrentChange"
      >
      </el-pagination>
      <div class="table-footer-tool">
        <SvgIcon name="iconfont icon-dayin" :size="19" title="打印" @click="onPrintTable" />
        <SvgIcon name="iconfont icon-yunxiazai_o" :size="22" title="导出" @click="onImportTable" />
        <SvgIcon name="iconfont icon-shuaxin" :size="22" title="刷新" @click="onRefreshTable" />
        <el-popover
          placement="top-end"
          trigger="click"
          transition="el-zoom-in-top"
          popper-class="table-tool-popper"
          :width="300"
          :persistent="false"
          @show="onSetTable"
        >
          <template #reference>
            <SvgIcon name="iconfont icon-quanjushezhi_o" :size="22" title="设置" />
          </template>
          <template #default>
            <div class="tool-box">
              <el-tooltip content="拖动进行排序" placement="top-start">
                <SvgIcon name="fa fa-question-circle-o" :size="17" class="ml11" color="#909399" />
              </el-tooltip>
              <el-checkbox
                v-model="state.checkListAll"
                :indeterminate="state.checkListIndeterminate"
                class="ml10 mr1"
                label="列显示"
                @change="onCheckAllChange"
              />
              <el-checkbox v-model="getConfig.isSerialNo" class="ml12 mr1" label="序号" />
              <el-checkbox v-model="getConfig.isSelection" class="ml12 mr1" label="多选" />
            </div>
            <el-scrollbar>
              <div ref="toolSetRef" class="tool-sortable">
                <div class="tool-sortable-item" v-for="v in header" :key="v.key" :data-key="v.key">
                  <i class="fa fa-arrows-alt handle cursor-pointer"></i>
                  <el-checkbox v-model="v.isCheck" size="default" class="ml12 mr8" :label="v.title" @change="onCheckChange" />
                </div>
              </div>
            </el-scrollbar>
          </template>
        </el-popover>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts" name="netxTable">
import { reactive, computed, nextTick, ref } from 'vue'
import { ElMessage } from 'element-plus'
import printJs from 'print-js'
import table2excel from 'js-table2excel'
import Sortable from 'sortablejs'
import { storeToRefs } from 'pinia'
import { useThemeConfig } from '/@/stores/themeConfig'
import '/@/theme/tableTool.scss'

// 定义父组件传过来的值
const props = defineProps({
  // 列表内容
  data: {
    type: Array<EmptyObjectType>,
    default: () => [],
  },
  // 表头内容
  header: {
    type: Array<EmptyObjectType>,
    default: () => [],
  },
  // 配置项
  config: {
    type: Object,
    default: () => {},
  },
  // 打印标题
  printName: {
    type: String,
    default: () => '',
  },
})

// 定义子组件向父组件传值/事件
const emit = defineEmits(['delRow', 'pageChange', 'sortHeader'])

// 定义变量内容
const toolSetRef = ref()
const storesThemeConfig = useThemeConfig()
const { themeConfig } = storeToRefs(storesThemeConfig)
const state = reactive({
  page: {
    pageNum: 1,
    pageSize: 10,
  },
  selectlist: [] as EmptyObjectType[],
  checkListAll: true,
  checkListIndeterminate: false,
})

// 设置边框显示/隐藏
const setBorder = computed(() => {
  return props.config.isBorder ? true : false
})
// 获取父组件 配置项（必传）
const getConfig = computed(() => {
  return props.config
})
// 设置 tool header 数据
const setHeader = computed(() => {
  return props.header.filter((v) => v.isCheck)
})
// tool 列显示全选改变时
const onCheckAllChange = <T>(val: T) => {
  if (val) props.header.forEach((v) => (v.isCheck = true))
  else props.header.forEach((v) => (v.isCheck = false))
  state.checkListIndeterminate = false
}
// tool 列显示当前项改变时
const onCheckChange = () => {
  const headers = props.header.filter((v) => v.isCheck).length
  state.checkListAll = headers === props.header.length
  state.checkListIndeterminate = headers > 0 && headers < props.header.length
}
// 表格多选改变时，用于导出
const onSelectionChange = (val: EmptyObjectType[]) => {
  state.selectlist = val
}
// 删除当前项
const onDelRow = (row: EmptyObjectType) => {
  emit('delRow', row)
}
// 分页改变
const onHandleSizeChange = (val: number) => {
  state.page.pageSize = val
  emit('pageChange', state.page)
}
// 分页改变
const onHandleCurrentChange = (val: number) => {
  state.page.pageNum = val
  emit('pageChange', state.page)
}
// 搜索时，分页还原成默认
const pageReset = () => {
  state.page.pageNum = 1
  state.page.pageSize = 10
  emit('pageChange', state.page)
}
// 打印
const onPrintTable = () => {
  // https://printjs.crabbly.com/#documentation
  // 自定义打印
  let tableTh = ''
  let tableTrTd = ''
  let tableTd: any = {}
  // 表头
  props.header.forEach((v) => {
    tableTh += `<th class="table-th">${v.title}</th>`
  })
  // 表格内容
  props.data.forEach((val, key) => {
    if (!tableTd[key]) tableTd[key] = []
    props.header.forEach((v) => {
      if (v.type === 'text') {
        tableTd[key].push(`<td class="table-th table-center">${val[v.key]}</td>`)
      } else if (v.type === 'image') {
        tableTd[key].push(`<td class="table-th table-center"><img src="${val[v.key]}" style="width:${v.width}px;height:${v.height}px;"/></td>`)
      }
    })
    tableTrTd += `<tr>${tableTd[key].join('')}</tr>`
  })
  // 打印
  printJs({
    printable: `<div style=display:flex;flex-direction:column;text-align:center><h3>${props.printName}</h3></div><table border=1 cellspacing=0><tr>${tableTh}${tableTrTd}</table>`,
    type: 'raw-html',
    css: ['//at.alicdn.com/t/c/font_2298093_rnp72ifj3ba.css', '//unpkg.com/element-plus/dist/index.css'],
    style: `@media print{.mb15{margin-bottom:15px;}.el-button--small i.iconfont{font-size: 12px !important;margin-right: 5px;}}; .table-th{word-break: break-all;white-space: pre-wrap;}.table-center{text-align: center;}`,
  })
}
// 导出
const onImportTable = () => {
  if (state.selectlist.length <= 0) return ElMessage.warning('请先选择要导出的数据')
  table2excel(props.header, state.selectlist, `${themeConfig.value.globalTitle} ${new Date().toLocaleString()}`)
}
// 刷新
const onRefreshTable = () => {
  emit('pageChange', state.page)
}
// 设置
const onSetTable = () => {
  nextTick(() => {
    const sortable = Sortable.create(toolSetRef.value, {
      handle: '.handle',
      dataIdAttr: 'data-key',
      animation: 150,
      onEnd: () => {
        const headerList: EmptyObjectType[] = []
        sortable.toArray().forEach((val: string) => {
          props.header.forEach((v) => {
            if (v.key === val) headerList.push({ ...v })
          })
        })
        emit('sortHeader', headerList)
      },
    })
  })
}

// 暴露变量
defineExpose({
  pageReset,
})
</script>

<style scoped lang="scss">
.table-container {
  display: flex;
  flex-direction: column;
  .el-table {
    flex: 1;
  }
  .table-footer {
    display: flex;
    .table-footer-tool {
      flex: 1;
      display: flex;
      align-items: center;
      justify-content: flex-end;
      i {
        margin-right: 10px;
        cursor: pointer;
        color: var(--el-text-color-regular);
        &:last-of-type {
          margin-right: 0;
        }
      }
    }
  }
}
</style>
