<script setup>
import { computed, onMounted, onUnmounted, ref } from 'vue';

const props = defineProps({
  items: {
    type: Array,
    required: true,
  },
  itemHeight: {
    type: Number,
    default: 80,
  },
  containerHeight: {
    type: Number,
    default: 400,
  },
});

const containerRef = ref(null);
const scrollTop = ref(0);

// 计算总高度
const totalHeight = computed(() => props.items.length * props.itemHeight);

// 计算可见区域的起始索引
const startIndex = computed(() =>
  Math.floor(scrollTop.value / props.itemHeight),
);

// 计算可见区域的结束索引
const endIndex = computed(() => {
  const visibleCount = Math.ceil(props.containerHeight / props.itemHeight);
  return Math.min(startIndex.value + visibleCount + 1, props.items.length - 1);
});

// 计算可见的项目
const visibleItems = computed(() => {
  return props.items
    .slice(startIndex.value, endIndex.value + 1)
    .map((item, index) => ({
      ...item,
      index: startIndex.value + index,
    }));
});

// 计算偏移量
const offsetY = computed(() => startIndex.value * props.itemHeight);

// 处理滚动事件
const handleScroll = (event) => {
  scrollTop.value = event.target.scrollTop;
};

// 监听容器大小变化
const resizeObserver = ref(null);

onMounted(() => {
  if (containerRef.value) {
    resizeObserver.value = new ResizeObserver((entries) => {
      for (const entry of entries) {
        const { height } = entry.contentRect;
        if (height !== props.containerHeight) {
          // 可以在这里触发高度变化事件
        }
      }
    });
    resizeObserver.value.observe(containerRef.value);
  }
});

onUnmounted(() => {
  if (resizeObserver.value) {
    resizeObserver.value.disconnect();
  }
});
</script>

<template>
  <div
    ref="containerRef"
    :style="{ height: `${containerHeight}px` }"
    class="virtual-list-container"
    @scroll="handleScroll"
  >
    <div
      :style="{ height: `${totalHeight}px` }"
      class="virtual-list-phantom"
    ></div>
    <div
      :style="{ transform: `translateY(${offsetY}px)` }"
      class="virtual-list-content"
    >
      <div
        v-for="item in visibleItems"
        :key="item.id"
        :style="{ height: `${itemHeight}px` }"
        class="virtual-list-item"
      >
        <slot :index="item.index" :item="item"></slot>
      </div>
    </div>
  </div>
</template>

<style scoped>
.virtual-list-container {
  position: relative;
  overflow-y: auto;
}

.virtual-list-phantom {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: -1;
}

.virtual-list-content {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
}

.virtual-list-item {
  box-sizing: border-box;
}
</style>
