<template>
  <div class="BasicSelect">
    <a-select v-bind="getBindValues">
      <template v-for="item in Object.keys($slots)" :key="item" #[item]="data">
        <slot v-bind="data" :name="item"></slot>
      </template>
    </a-select>
  </div>
</template>

<script lang="ts" setup>
  import { ref, unref, computed, onMounted, useAttrs } from 'vue';
  import { basicProps } from './props';
  import { createStorage } from '@/utils/Storage';

  const Storage = createStorage({ storage: localStorage });

  const props = defineProps({ ...basicProps });

  const loading = ref(true);

  const options = ref([]);

  const attrs = useAttrs();

  const getProps = computed(() => {
    return { ...props } as basicProps;
  });

  const selectWidth = props.block ? '100%' : `${props.width}px`;

  const getBindValues = computed(() => {
    return {
      ...unref(getProps),
      loading: loading.value,
      options: options.value,
      ...attrs,
    };
  });

  const getCacheData = computed(() => {
    return props.cacheKey ? Storage.get(props.cacheKey) : null;
  });

  //初始化
  function init() {
    const { cache, cacheKey } = props;
    //判断是否启用缓存
    if (cache && cacheKey && getCacheData.value) {
      options.value = getCacheData.value || [];
      loading.value = false;
      return;
    }
    //获取新数据
    fetch();
  }

  //触发取新数据
  async function fetch() {
    loading.value = true;
    const { request, cacheKey } = props;
    try {
      const res = await request();
      options.value = res || [];
      loading.value = false;
      Storage.set(cacheKey, res);
    } catch (error) {
      console.error(error);
    }
  }

  //获取数据源
  function getData() {
    const { cache, cacheKey } = props;
    return cache && cacheKey ? Storage.get(props.cacheKey) : options.value;
  }

  //获取缓存
  onMounted(() => {
    init();
  });

  //暴露方法
  defineExpose({
    fetch,
    getData,
  });
</script>

<style lang="less" scoped>
  .BasicSelect {
    display: inline-block;
    width: v-bind(selectWidth);

    .ant-select {
      width: 100%;
    }
  }
</style>
