<template>
  <el-table :data="list" border stripe @selection-change="toSelect">
    <el-table-column type="selection" width="55" v-if="select"> </el-table-column>
    <template v-for="(item, index) in fields">
      <template v-if="item.custom">
        <el-table-column :key="index" :label="item.label" v-bind="item.options" align="center" :show-overflow-tooltip="item.showTip || true">
          <template v-slot="{ row }">
            <slot :name="item.model" v-bind="{ item, row }"></slot>
          </template>
        </el-table-column>
      </template>
      <template v-else>
        <el-table-column
          :key="index"
          :label="item.label"
          :prop="item.model"
          :formatter="toFormatter"
          v-bind="item.options"
          :sortable="true"
          align="center"
          :show-overflow-tooltip="item.showTip === false ? item.showTip : true"
        ></el-table-column>
      </template>
    </template>
    <template v-if="opera.length > 0">
      <el-table-column label="操作" fixed="right" width="110" align="center">
        <template v-slot="{ row, $index }">
          <template v-for="(item, index) in opera">
            <template v-if="display(item, row)">
              <template v-if="vOpera">
                <el-link
                  :key="`${item.model}-column-${index}`"
                  :type="item.type || 'primary'"
                  size="small"
                  :underline="false"
                  class="link"
                  v-opera="item.method"
                  @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index, item.confirmWord)"
                >
                  {{ item.label }}
                </el-link>
              </template>
              <template v-else>
                <el-link
                  :key="`${item.model}-column-${index}`"
                  :type="item.type || 'primary'"
                  size="small"
                  :underline="false"
                  class="link"
                  @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index, item.confirmWord)"
                >
                  {{ item.label }}
                </el-link>
              </template>
            </template>
          </template>
        </template>
      </el-table-column>
    </template>
  </el-table>
  <el-row justify="end" class="page" v-if="usePage">
    <el-pagination
      background
      layout="sizes,total, prev, pager, next"
      :page-sizes="[10, 20, 50, 100, 200]"
      :total="total"
      :page-size="limit"
      v-model:current-page="currentPage"
      @current-change="changePage"
      @size-change="sizeChange"
    >
    </el-pagination>
  </el-row>
</template>

<script setup lang="ts">
// 基础
import _ from 'lodash'
import type { Ref } from 'vue'
import { onMounted, toRefs, getCurrentInstance, ref } from 'vue'
import { ElMessageBox } from 'element-plus'
const { proxy } = getCurrentInstance() as any
const emit = defineEmits(['toSelect', 'query'])

// 参数
interface fieldsItem {
  // 是否自定义
  custom: string
  // 名称
  label: string
  // 绑定键值
  model: string
  // 其他
  options: string
  // 是否超出隐藏
  showTip: boolean
}
interface operaItem {
  // 名称
  label: string
  model: string
  // 绑定键值
  method: string
  // 颜色
  type: string
  // 是否开启弹框
  confirm: boolean
  // 是否自定义文字说明
  confirmWord: string
  // 简短文字
  methodZh: string
}
interface dataItem {
  _id?: string
}

const props = defineProps({
  // 列表配置
  fields: { type: Array<fieldsItem>, required: true },
  // 操作配置
  opera: { type: Array<operaItem>, required: true },
  // 列表数据
  list: { type: Array<dataItem>, required: true },
  // 是否开启多选
  select: { type: Boolean, default: false },
  // selected: { type: Array, default: () => [] },
  vOpera: { type: Boolean, default: false },
  // 分页
  usePage: { type: Boolean, default: true },
  total: { type: Number, default: 0 }
})
const { fields } = toRefs(props)
const { opera } = toRefs(props)
const { list } = toRefs(props)
const { select } = toRefs(props)
// const { selected } = toRefs(props);
const { vOpera } = toRefs(props)
const { usePage } = toRefs(props)
const { total } = toRefs(props)

let limit: number = proxy.$limit
let currentPage: Ref<number> = ref(1)
// 请求
onMounted(async () => {})
// 多选
const toSelect = (val: Array<[]>) => {
  emit(`toSelect`, val)
}
// 格式化内容
const toFormatter = (row: any, column: { property: string }, cellValue: string) => {
  let this_fields = fields.value.filter((fil) => fil.model === column.property)
  if (this_fields.length > 0) {
    let format: any = _.get(this_fields[0], `format`, false)
    if (format) {
      let res
      if (_.isFunction(format)) {
        res = format(cellValue)
      } else {
        res = toFormat({ model: this_fields[0].model, value: cellValue })
      }
      return res
    } else {
      return cellValue
    }
  }
}
const toFormat = (e: { model: string; value: string }) => {
  console.log(e)
}
// 过滤
const display = (item: operaItem, row: any) => {
  let display: any = _.get(item, `display`, true)
  if (display === true) return true
  else {
    let res = display(row)
    return res
  }
}
// 操作
const handleOpera = (data: string, method: any, confirm = false, methodZh: string, label: string, index: string, confirmWord: string) => {
  let self = true
  if (_.isFunction(methodZh)) methodZh = methodZh(data)
  else if (!_.isString(methodZh)) {
    methodZh = label
    self = false
  }
  if (confirm) {
    let word = self ? methodZh : `您确认${methodZh}该数据?`
    if (confirmWord) word = confirmWord
    ElMessageBox.confirm(word, '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
      .then(() => {
        emit(method, data, index)
      })
      .catch(() => {})
  } else emit(method, data, index)
}
// 分页
const changePage = (page: number = currentPage.value) => {
  emit('query', { skip: (page - 1) * limit, limit: limit })
}
const sizeChange = (limits: number) => {
  limit = limits
  currentPage.value = 1
  emit('query', { skip: 0, limit: limit })
}
</script>
<style scoped lang="scss">
.link {
  padding: 0 5px 0 0;
}
.page {
  margin: 10px 0 0 0;
}
</style>
