<script setup lang="ts">
import type { PropsParams } from '@/types/table'
import { FilterType, FieldSpecialEffectType } from '@/types/table'

import { computed, onMounted, reactive, ref, watch } from 'vue'
import { useTable } from '@/hooks/useTable'

import FilterPopover from './toolsBtn/FilterPopover.vue'
import RegreshBtn from './toolsBtn/RegreshBtn.vue'

import type { FormInstance } from 'element-plus'

// 表格工具图标大小
const toolsIconSize = ref(25)

// 查询表单
const queryFormRef = ref<FormInstance>()

// 传过来的配置
const props = defineProps<PropsParams>()

const emits = defineEmits(['addNewItem'])

// 表格数据
const tableData: Array<any> = reactive([])

// 查询表单的数据
const queryFormData = reactive<any>({})

// 一些公用方法
const { getTableData } = useTable(tableData, props.paginationConfig)

// 所有类型为input的表单控件信息
const inputFieldsList = computed(() => {
  return props.queryInfo?.filter((item) => item.type === FilterType.INPUT)
})

// 所有类型为select的表单控件信息
const selectFieldsList = computed(() => {
  return props.queryInfo?.filter((item) => {
    if (item.default) {
      queryFormData[item.name] = item.default
    }
    return item.type === FilterType.SELECT
  })
})
console.log(selectFieldsList)
// 所有类型为date的表单控件信息
const dateFieldsList = computed(() => {
  return props.queryInfo?.filter((item) => item.type === FilterType.DATE)
})

// 改变页码
const handleCurrentChange = (val: number) => {
  props.paginationConfig.currentPage = val
}

// 改变每页大小
const handleSizeChange = (val: number) => {
  props.paginationConfig.limit = val
}

// 获取数据
const getData = () => {
  if (props.openPageQuery) {
    // 如果开启了分页查询，那么要计算出需要展示的页码位置所对应的偏移量
    // 同时要将查询的条数改为对应的用户选择的展示条数
    props.requestConfig.other.offset =
      (props.paginationConfig.currentPage - 1) * props.paginationConfig.limit
    props.requestConfig.other.limit = props.paginationConfig.limit
  }

  // 查询时要根据是否开启分页查询传入对应参数
  getTableData(props.requestConfig.url, props.requestConfig.other, props.openPageQuery)
}

// 清空表格数据
const resetTableData = () => {
  tableData.splice(0, tableData.length)
}

// 根据分页大小的切换来更新数据
// 这里将他赋值，用于根据传入的配置来选择是否开启该监听
const changePageLimit = watch(
  () => [props.paginationConfig.limit, props.paginationConfig.currentPage],
  ([newLimit], [oldLimit]) => {
    if (newLimit != oldLimit) {
      // 需要给分页按钮加上:current-page.sync="current_page" 配置，不然不生效
      // 当改变每页大小时把之前的缓存全部清除，重新开始
      props.paginationConfig.currentPage = 1
      resetTableData()
      getData()
    } else if (!tableData[props.paginationConfig.currentPage]) {
      // 当对应的数组下标位置没有这页的数据的时候再去请求
      getData()
    }
  },
  { deep: true }
)

// 按条件查询
const queryTableData = () => {
  props.requestConfig.other = { ...props.requestConfig.other, ...queryFormData }
  getData()
}

// 重置查询的条件
const resetQueryForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl?.resetFields()
}

// 没有开启分页查询就关闭掉这个监听
if (!props.openPageQuery) changePageLimit()

// 定义暴露出去的方法
defineExpose({
  getData,
  resetTableData
})

onMounted(() => {
  getData()
})
</script>

<template>
  <div class="tableContent">
    <div class="filterBox" v-if="openFilterQuery">
      <!-- slot -->
      <div class="filterHeader">
        <span>查询条件</span>
      </div>
      <div class="filterBody">
        <el-form
          :inline="true"
          ref="queryFormRef"
          :model="queryFormData"
          class="queryForm"
          :label-position="'left'"
        >
          <!-- 所有的input查询框 -->
          <el-form-item :label="item.label" v-for="item in inputFieldsList" class="filterItem">
            <el-input
              v-model="queryFormData[item.name]"
              :placeholder="item.placeholder"
              clearable
            />
          </el-form-item>

          <!-- 所有选择框 -->
          <el-form-item :label="item.label" v-for="item in selectFieldsList" class="filterItem">
            <el-select v-model="queryFormData[item.name]" :placeholder="item.placeholder">
              <el-option v-for="val in item.otherOption" :label="val.cnName" :value="val.value" />
            </el-select>
          </el-form-item>

          <!-- 所有日期选择框 -->
          <el-form-item :label="item.label" v-for="item in dateFieldsList" class="filterItem">
            <el-date-picker
              v-model="queryFormData[item.name]"
              type="date"
              :placeholder="item.placeholder"
              clearable
            />
          </el-form-item>
        </el-form>
        <!-- 分割线 -->
        <!-- <el-divider class="queryPartition" content-position="center" direction="vertical" /> -->
        <div class="queryBox">
          <el-divider class="queryPartition" content-position="center" direction="vertical" />
          <div class="queryBtnBox">
            <el-button class="queryBtn" color="#165dff" @click="queryTableData">
              <el-icon><Search /></el-icon>查询
            </el-button>
            <el-button class="refreshBtn" color="#f2f3f5" @click="resetQueryForm(queryFormRef)">
              <el-icon><RefreshRight /></el-icon>重置
            </el-button>
          </div>
        </div>
      </div>
    </div>
    <!-- 分割线 -->
    <el-divider class="partition" content-position="center" />
    <div class="tableTools">
      <div class="leftTools">
        <el-button v-if="needLeftTools" type="primary" color="#165dff" @click="emits('addNewItem')">
          <el-icon><Plus /></el-icon>新增
        </el-button>
      </div>
      <div class="rightTools">
        <el-button color="#f0f1f3" size="default" class="rightToolsItem">
          <el-icon><Download /></el-icon>下载
        </el-button>

        <RegreshBtn @refresh-table="getData" :icon-size="toolsIconSize"></RegreshBtn>

        <FilterPopover
          :table-fields-info="tableFieldsInfo"
          :icon-size="toolsIconSize"
        ></FilterPopover>
      </div>
    </div>

    <div class="tableBox">
      <el-table
        :data="openPageQuery ? tableData[paginationConfig.currentPage] : tableData"
        style="width: 100%"
        class="tableBody"
      >
        <el-table-column align="center" label="#" type="index" :index="1" />
        <template v-for="item in tableFieldsInfo">
          <el-table-column
            :prop="item.name"
            :label="item.cnName"
            width="auto"
            align="center"
            show-overflow-tooltip
            v-if="item.isShow"
          >
            <template v-slot="scope">
              <!-- tag类 -->
              <el-tag
                v-if="item.specialEffect?.type === FieldSpecialEffectType.TAG"
                :type="scope.row[item.name] ? 'danger' : 'success'"
              >
                {{
                  scope.row[item.name]
                    ? item.specialEffect.othnerInfo[0]
                    : item.specialEffect.othnerInfo[1]
                }}
              </el-tag>

              <!-- 头像类 -->
              <el-image
                v-else-if="item.specialEffect?.type === FieldSpecialEffectType.IMG"
                :preview-teleported="true"
                :src="scope.row[item.name]"
                :preview-src-list="[scope.row[item.name]]"
                style="width: 35px; height: 35px"
                :fit="'fill'"
                :hide-on-click-modal="true"
              >
                <template #error>
                  <!--  -->
                  <img style="width: 35px; height: 35px" src="../assets/default/defaultHead.png" />
                </template>
              </el-image>

              <!-- 文字类 -->
              <el-text
                v-else-if="item.specialEffect?.type === FieldSpecialEffectType.TEXT"
                :type="scope.row[item.name] ? 'danger' : 'success'"
              >
                {{ scope.row[item.name] }}
              </el-text>

              <!-- 翻译类 -->
              <el-text v-else-if="item.specialEffect?.type === FieldSpecialEffectType.TRANSLATE">
                {{ item.specialEffect.othnerInfo[scope.row[item.name]] }}
              </el-text>

              <el-text v-else>
                <!-- 其他列按默认方式显示 -->
                {{ scope.row[item.name] }}
              </el-text>
            </template>
          </el-table-column>
        </template>

        <slot name="tableOperation"></slot>
      </el-table>
      <div class="userTablePaginationBox">
        <el-pagination
          class="userTablePagination"
          background
          :page-size="paginationConfig.limit"
          :page-sizes="paginationConfig.pagesizeList"
          table-layout="fixed"
          layout="prev, pager, next ,jumper ,sizes,total,"
          :total="paginationConfig.total"
          :current-page.sync="paginationConfig.currentPage"
          @current-change="handleCurrentChange"
          @size-change="handleSizeChange"
        />
      </div>
    </div>
  </div>
</template>

<style scoped>
.tableContent {
  margin: 0 auto;
  width: 98%;
  /* height: 100%; */
}
.filterBox,
.tableBox {
  width: 100%;
}

.filterBox {
  margin-top: 1%;
  min-height: 18%;
  display: flex;
  flex-direction: column;
}

.filterHeader,
.filterBody {
  width: 98%;
  margin: 0 auto;
}

.filterHeader {
  display: flex;
  align-items: center;
  color: black;
  font-size: 20px;
  font-weight: bold;
  /* background-color: lightblue; */
  /* margin-bottom: 1%; */
}

.filterBody {
  display: flex;
}

.queryBox {
  width: 10%;
  display: flex;
  justify-content: space-around;
}

.queryBtnBox {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.refreshBtn {
  margin-top: 10%;
  margin-bottom: 10%;
}

.queryPartition {
  height: 90%;
}

.queryForm {
  width: 90%;
  display: flex;
  flex-wrap: wrap;
  /* justify-content: space-between; */
}

.filterItem {
  width: 30%;
  display: flex;
  align-items: center;
}

.partition {
  width: 98%;
  margin: 0 auto;
}

.tableTools {
  width: 98%;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  margin-top: 1%;
}

.leftTools,
.rightTools {
  width: 10%;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.rightTools {
  width: 10%;
}

.tableBox {
  width: 98%;
  /* height: 98%; */
  margin: 0 auto;
  /* margin-top: 0.5%;
  margin-bottom: 2%; */
}

.userTablePaginationBox {
  width: 98%;
  margin: 0.5% auto;
  display: flex;
  justify-content: center;
}
</style>
