<!--
 * @Description: 列表页通用页面
 * @Author: ZCY
 * @Date: 2023年2月8日12:25:03
-->
<script lang="ts" setup>
import { computed, ref, useSlots, watch } from 'vue';
import { formatDate } from '@unyu/utils';
import ReloadIcon from './components/ReloadIcon.vue';
import FilterCogIcon from './components/FilterCogIcon.vue';
import VerticalDensityIcon from './components/VerticalDensityIcon.vue';
import type { UTableProps } from './types';
import ExportIcon from './components/ExportIcon.vue';
import ImportIcon from './components/ImportIcon.vue';

const props = withDefaults(defineProps<UTableProps>(), {
  density: 'default',
  striped: false,
  showHeader: true,
  showExpandColumn: true,
  showSorterTooltip: true,
  loading: false,
});

const emits = defineEmits<TableListEmits>();

defineOptions({
  inheritAttrs: false
});

const slots = useSlots();

interface TableListEmits {
  (e: 'export'): void;
  (e: 'import'): void;
  (e: 'refresh'): void;
}

const tools = computed(() => props.tools?.split(' ') || []);

/**
 * ----------------------------- 刷新数据 -----------------------------
 */
const onRefreshData = () => {
  emits('refresh');
};

/**
 * ----------------------------- 数据导出 -----------------------------
 */
const onExportData = () => {
  emits('export');
};

/**
 * ----------------------------- 数据导出 -----------------------------
 */
const onImportData = () => {
  emits('import');
};

/**
 * ----------------------------- 筛选列 -----------------------------
 */
const checkedKeys = ref<string[]>([]);

const filterColumns = computed(() => {
  return props.columns?.filter(col => checkedKeys.value.includes(col?.dataIndex as string)) || [];
});
const filterColOpt = computed(() => props.columns?.map(col => ({
  value: col?.dataIndex as any,
  label: col?.title as string
})) || []);

watch(() => props.columns, () => {
  checkedKeys.value = props.columns?.map(col => col?.dataIndex as string) || [];
}, {
  immediate: true
});

/**
 * ----------------------------- 表格行密度切换 -----------------------------
 */
const size = ref(props.density);
const sizeOpen = ref(false);

const onSizeChange = (value: UTableProps['density']) => {
  size.value = value!;
  sizeOpen.value = false;
};
</script>

<template>
  <a-table
    v-bind="props"
    class="u-table"
    :class="{
      'u-table-striped': striped,
      'u-table-size-compact': size === 'compact',
      'u-table-size-default': size === 'default',
      'u-table-size-loose': size === 'loose'
    }"
    :loading="loading"
    :columns="filterColumns"
  >
    <template v-for="(slot, name) in slots" :key="name" #[name]="slotProps">
      <slot :name="name" v-bind="slotProps" />
    </template>
    <template #bodyCell="data">
      <template v-if="(data.column as any)?.dateFormat">
        {{ formatDate(new Date(data.text), (data.column as any)?.dateFormat) }}
      </template>
      <slot name="bodyCell" v-bind="data" />
    </template>
    <template v-if="tools.length" #title>
      <div class="u-table-title">
        <slot name="title" style="flex: 1">
          {{ title }}
        </slot>
        <div v-if="tools.length" class="u-table-tools">
          <template v-for="name in tools" :key="name">
            <ReloadIcon v-if="name === 'refresh'" :loading="loading" @click="onRefreshData">
              <slot v-if="slots.refreshIcon" name="refreshIcon" />
            </ReloadIcon>
            <ImportIcon v-if="name === 'import'" @click="onImportData">
              <slot v-if="slots.importIcon" name="importIcon" />
            </ImportIcon>
            <ExportIcon v-if="name === 'export'" @click="onExportData">
              <slot v-if="slots.exportIcon" name="exportIcon" />
            </ExportIcon>
            <VerticalDensityIcon v-if="name === 'size'" v-model:open="sizeOpen" :size="size" @change="onSizeChange">
              <slot v-if="slots.sizeIcon" name="sizeIcon" />
            </VerticalDensityIcon>
            <FilterCogIcon v-if="name === 'filter'" v-model:checked-keys="checkedKeys" :columns="filterColOpt">
              <slot v-if="slots.filterIcon" name="filterIcon" />
            </FilterCogIcon>
          </template>
        </div>
      </div>
    </template>
  </a-table>
</template>

<style scoped>
.u-table {
  position: relative;
  width: 100%;
}
.u-table :deep(.ant-table-cell-row-hover) {
  background-color: whitesmoke;
}
.u-table :deep(.ant-table-title) {
  border: none !important;
  padding: 8px;
}
.u-table-title {
  position: relative;
  width: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.u-table-tools {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  margin-left: 8px;
  font-size: 18px;
  color: #555;
}
.u-table-tools svg {
  cursor: pointer;
}
.u-table-tools svg:focus {
  outline: none;
}
.u-table-tools svg:hover {
  opacity: 80%;
}

.spin-animation {
  animation: spin 1s infinite linear;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
.u-table-size-compact :deep(.ant-table-cell) {
  padding: 8px 12px !important;
}

.u-table-size-default :deep(.ant-table-cell) {
  padding: 10px 14px !important;
}

.u-table-size-loose :deep(.ant-table-cell) {
  padding: 14px 16px !important;
}
</style>
