<script setup lang="ts" generic="T extends AnyObject"> import { UnwrapRef } from 'vue' const props = withDefaults( defineProps<{ request?: (query: Partial<T>) => Promise<IResData<T[]>> items?: T[] query?: Partial<T> automatic?: boolean mockList?: Partial<T>[] contentClass?: string }>(), { automatic: true, query: () => ({}), contentClass: 'flex flex-col', }, ) const slot = defineSlots<{ default(props: { item: UnwrapRef<T>; index: number; isLast: boolean }): any }>() const request = computed(() => { if (props.request) { return props.request } else { return async () => { return { code: 0, msg: '', data: props.items } } } }) const { data, run: setData } = useRequest(() => request.value({ ...props.query }), { immediate: false, }) onMounted(async () => { if (props.mockList) { data.value = props.mockList as T[] return } if (props.automatic) { await setData() } }) watch( () => props.query, async () => { if (props.mockList) { data.value = props.mockList as T[] return } await setData() }, ) defineExpose({ reload: async () => { await setData() }, }) </script> <template> <div class="flex-grow relative flex flex-col"> <div :class="contentClass"> <template v-for="(it, index) in data" :key="index"> <slot :item="it as UnwrapRef<T>" :index="index" :isLast="index == (data?.length ?? 0) - 1" ></slot> </template> </div> <div v-if="mockList" class="construction-dashed absolute top-0 right-0 left-0 bottom-0 bg-red/20 flex items-center justify-center pointer-events-none" > <div class="text-16 text-black/30">Debug</div> </div> </div> </template> <style scoped lang="scss"> //@layer utilities { .construction-dashed { @apply border-4 border-black/50 border-dashed; /* 基础虚线样式 */ animation: dashed-move 2s linear infinite; /* 虚线移动动画 */ } //} @keyframes dashed-move { from { border-spacing: 0; } to { border-spacing: 10px; } } </style>