<template>
  <div class="business-table">
    <el-table
      ref="tableRef"
      :data="cData"
      :height="'100%'"
      :width="'100%'"
      :cell-style="tableConfig.cellStyleFunc"
      :row-style="tableConfig.rowStyleFunc"
      :id="tableConfig.tableId || tableId"
      :default-sort="tableConfig.defaultSort"
      class="el-table--scrollable-y"
      :show-summary="tableConfig.hasSummary"
      :summary-method="tableConfig.summaryMethod"
      :span-method="tableConfig.spanMethod"
      :tree-props="tableConfig.treeProps"
      :lazy="tableConfig.lazy"
      :load="tableConfig.load"
      :row-class-name="tableConfig.rowClassNameFun"
      :row-key="tableConfig.rowKey"
      header-row-class-name="table-header"
      v-bind="$attrs"
      @cell-click="tableConfig.cellClick"
      @selection-change="handleSelectionChange"
      @sort-change="sortChange"
    >
      <el-table-column
        v-if="tableConfig.multipleSelect"
        :reserve-selection="tableConfig.reserveSelect"
        :selectable="tableConfig.selectable"
        type="selection"
        header-align="center"
        align="center"
      />
      <slot />
      <slot
        name="control-column"
        :canDelete="mergePermissions.delete"
        :canModify="mergePermissions.modify"
        :canDetail="mergePermissions.detail"
        :modifyMethod="modify"
        :removeMethod="remove"
        :detailMethod="showDetail"
      >
        <el-table-column
          fixed="right"
          align="center"
          class-name="control-column"
          label="操作"
          :width="tableConfig.controlWidth"
          v-if="tableConfig.hasControlColumn"
        >
          <template #default="scope">
            <template v-if="mergePermissions.canModifyCustom(scope.row)">
              <el-link
                type="primary"
                v-if="mergePermissions.modify"
                @click="modify(scope.row)"
                title="修改"
              >
                修改
              </el-link>
            </template>
            <template v-if="mergePermissions.canDeleteCustom(scope.row)">
              <el-link
                type="primary"
                v-if="mergePermissions.delete"
                @click="remove(scope.row)"
                title="删除"
              >
                删除
              </el-link>
            </template>
            <template v-if="mergePermissions.canDetailCustom(scope.row)">
              <el-link
                type="primary"
                @click="showDetail(scope.row)"
                title="详情"
                v-if="mergePermissions.detail"
              >
                详情
              </el-link>
            </template>
            <slot
              name="otherControlButtons"
              :data="scope"
            />
          </template>
        </el-table-column>
      </slot>
    </el-table>

    <el-pagination
      v-if="hasPagerBar"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      v-model:current-page="pagination.page"
      :page-sizes="tableConfig.pageSizes"
      v-model:page-size="pagination.pageSize"
      :layout="tableConfig.pagerLayout"
      :total="pagination.total"
      background
    >
      <template #default>
        <span
          class="pager total"
          :class="{ link: pageUnlimitCondition }"
          @click="queryUnLimit"
        >
          {{ pagerTotal }}
        </span>
      </template>
    </el-pagination>
  </div>
</template>

<script setup>
import {ref, reactive, computed, watch, onMounted, nextTick, getCurrentInstance} from 'vue'
  import {ElMessage, ElMessageBox} from 'element-plus'
  import { DATA_FLAGS } from '../utils/Constants'
  import watermark from '@/utils/WarterMark'
  import { v4 as uuid } from 'uuid'
  import { merge } from 'lodash'
  import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
  import { useUserStore } from '@/stores/modules/user'
  import {
    exportExcelFile,
    toExportExcelFileByUrl,
    toExportXmlAllFileByUrl,
    toExportXmlSelectFileByUrl
  } from "@/utils/ExportExcel.js";

  const userStore = useUserStore()
  const emit = defineEmits([
    'query-params',
    'do-query',
    'show-detail',
    'show-modify',
    'do-remove',
    'table-selection',
    'do-customize',
  ])

  const defaultConfig = {
    tableLoading: false,
    hasControlColumn: false,
    controlWidth: '300',
    pageSizes: [20, 40, 60, 100],
    usePage: true,
    multipleSelect: true,
    selectable: null,
    reserveSelect: false,
    cellStyleFunc: null,
    rowStyleFunc: null,
    rowClassNameFun: null,
    hasSummary: false,
    summaryMethod: null,
    spanMethod: null,
    userInfo: {},
    defaultSort: {},
    treeProps: { children: 'children', hasChildren: 'hasChildren' },
    useWaterMark: true,
    istick: false,
    pagerLayout: '->, slot, sizes, prev, pager, next'
  }

  const props = defineProps({
    queryParams: {
      type: Object,
      default: () => ({}),
    },
    config: Object,
    dataRes: {
      type: Object,
      default: () => ({}),
    },
    permissions: {
      type: Object,
      default: () => ({
        modify: false,
        delete: false,
        detail: true,
        canDeleteCustom: () => true,
        canDetailCustom: () => true,
        canModifyCustom: () => true,
      }),
    },
  })

  const defaultPermissions = {
    modify: false,
    delete: false,
    detail: true,
    canDeleteCustom: () => true,
    canDetailCustom: () => true,
    canModifyCustom: () => true,
  }

  const tableConfig = reactive(merge({}, defaultConfig, props.config))
  const mergePermissions = reactive(merge({}, defaultPermissions, props.permissions))
  // 响应式状态
  const pagination = reactive({
    page: 1,
    pageSize: tableConfig.pageSizes[0] || 20,
    total: 0,
  })

  const { proxy } = getCurrentInstance()

  props.queryParams

  const data = ref([])
  const once = ref(true)
  const tableHeaderLabel = ref([])
  const tableHeaderProps = ref([])

  // 计算属性
  const cData = computed(() => data.value.filter((d) => !d.dataFlag || d.dataFlag !== DATA_FLAGS.REMOVE))

  const pagerTotal = computed(() => {
    const totalVal = pagination.total || 0
    return totalVal === 0 || props.dataRes.relation === 'eq' ? `共${totalVal}条` : `>=${totalVal}条`
  })

  const pageUnlimitCondition = computed(() => props.dataRes.relation === 'gte' && props.queryParams.limit && !tableConfig.tableLoading)

  const hasPagerBar = computed(() => tableConfig.usePage)

  const tableId = computed(() => uuid())

  // 生命周期
  onMounted(() => {
    if (tableConfig.useWaterMark) {
      watermark.set('el-table', { username: userStore.username, mobile: userStore.mobile })
    }
    initQueryParams()
  })

  // 方法
  const initQueryParams = () => {
    emit('query-params', {
      // 查询参数
      ...props.queryParams,
      //
      page: pagination.page,
      pageSize: pagination.pageSize,
      // 兼容旧接口
      pagesize: pagination.pageSize,
      // 初始化默认排序
      sort: tableConfig.defaultSort.prop,
      dir: tableConfig.defaultSort.order,
    })
  }

  const query = (pageNum) => {
    emit('query-params', {
      ...props.queryParams,
      page: pageNum,
      total: pagination.total,
    })
    emit('do-query')
  }

  const handleSizeChange = (size) => {
    pagination.pageSize = size
    pagination.page = 1
    emit('query-params', { pagesize: size, pageSize: size })
  }

  const handleCurrentChange = (current) => {
    pagination.page = current
    query(current)
  }

  const showDetail = (row) => {
    if (mergePermissions.detail) {
      emit('show-detail', row)
    }
  }

  const modify = (row) => {
    if (mergePermissions.modify) {
      emit('show-modify', row)
    }
  }
  const remove = (row) => {
    if (mergePermissions.delete) {
      ElMessageBox.confirm('是否要删除选中的数据?', '确认', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
      }).then(() => emit('do-remove', row))
      .catch(() => {})
    }
  }

  const handleSelectionChange = (val) => {
    if (tableConfig.multipleSelect) {
      emit('table-selection', val)
    }
  }



  const sortChange = ({ prop, order, column }) => {
    const dir = order === 'descending' ? 'desc' : 'asc'
    emit('query-params', {
      ...props.queryParams,
      sort: column.sortBy || prop,
      dir: dir,
    })
    if (!once.value) emit('do-query')
    once.value = false
  }

  const queryUnLimit = () => {
    if (pageUnlimitCondition.value) {
      emit('query-params', {
        ...props.queryParams,
        limit: false,
        total: 0,
      })
      emit('do-query')
    }
  }

  const resetQuery = () => {
    // 重置时不保留之前的查询参数，只设置分页相关参数
    emit('query-params', {
      page: 1,
      total: 0,
      pageSize: pagination.pageSize,
    })
    pagination.page = 1
    once.value = true
  }

  const exportExcelFileForCurrentPage = (tableId, excelFileName) => { // 导出当前页数据为excel(不访问后台)
    if (pagination.total === 0) {
      ElMessage.warning('没有数据可以导出！')
      return
    }
    exportExcelFile(tableId, excelFileName)
  }
  const exportExcelFileForAllData = (url, excelFileName, params) => { // 导出table页中所有数据，需要传入到后台进行查询并组装excel,params为自定义参数用于配合在后台对应的查询条件
    if (pagination.total === 0) {
      ElMessage.warning('没有数据可以导出！')
      return
    }
    toExportExcelFileByUrl(url, tableHeaderLabel.value, tableHeaderProps.value, excelFileName, params, proxy)
  }
  const exportXmlSelectFileForData = (url, codeList) => {
    if (codeList.length === 0) {
      ElMessage.warning('没有数据可以导出！')
      return
    }
    toExportXmlSelectFileByUrl(url, codeList, '企业XML格式数据', {}, proxy)
  }
  const exportXmlAllFileForData = (url, params) => {
    toExportXmlAllFileByUrl(url, '企业XML格式数据', params, proxy)
  }

  // 数据监听
  watch(
    () => props.dataRes,
    (val) => {
      if (val?.success) {
        data.value = tableConfig.istick ? [] : val.data
        pagination.total = val.total
        if (once.value) {
          once.value = false
        }
      }
    },
    { immediate: true, deep: true }
  )

  watch(
    () => pagination.page,
    (newVal, oldVal) => {
      if (newVal !== oldVal) query(newVal)
    }
  )
  defineExpose({
    query,
    resetQuery,
    exportExcelFileForCurrentPage,
    exportExcelFileForAllData,
    exportXmlSelectFileForData,
    exportXmlAllFileForData
  })
</script>
<style lang="scss" scoped>
.business-table {
  // 给表格添加圆角
  border-radius: 8px;
    overflow: hidden;
  :deep(.el-table) {
    // 给表格添加圆角
    border-radius: 8px;
    overflow: hidden;

    // 设置表头背景色
    .el-table__header th {
      background-color: #D1E5FB !important;
    }

    // 设置表格内容行的样式
    .el-table__row {
      background-color: #ffffff;

      // 斑马纹样式
      &:nth-child(even) {
        background-color: #D9E1F3;
      }
    }

    .el-table__cell {
      font-size: 1rem;
    }
  }

  // 给分页组件添加圆角
  ::v-deep(.el-pagination) {
    border-radius: 8px;
    overflow: hidden;
    margin-top: 10px;
    padding: 10px;
    background-color: transparent;
  }

  .control-column {
    .el-link {
      margin-right: 10px;

      &:last-child {
        margin-right: 0;
      }

      &.el-link--primary {
        color: var(--el-color-primary);
      }

      &.el-link--danger {
        color: var(--el-color-danger);
      }

      &.el-link--info {
        color: var(--el-color-info);
      }

      svg {
        margin-right: 2px;
      }
    }
  }
}
</style>
