<script setup lang="ts"> import { watch, ref } from 'vue'; interface Props { list: any[]; autoplay: number; } const props = withDefaults(defineProps<Props>(), { list: () => [], autoplay: 10000, }); const slide = ref('1'); watch( () => props.list, (newVal, oldVal) => { listChange(newVal, oldVal); } ); function listChange(newVal: any, oldVal: any) { console.log('newVal', newVal.length, 'oldVal', oldVal.length); if (oldVal.length < newVal.length && oldVal.length === 1) { setTimeout(() => { slide.value = '2'; }, props.autoplay); } if (newVal.length < Number(slide.value)) { slide.value = '1'; } } function clickPoint(value: string) { if (value !== slide.value) { slide.value = value; } } </script> <template> <div class="my-carousel-box"> <template v-if="props.list.length > 0"> <div class="content"> <q-carousel v-model="slide" transition-prev="slide-right" transition-next="slide-left" animated infinite :keep-alive="false" :autoplay="props.autoplay" class="my-carousel" > <q-carousel-slide :name="String(index + 1)" class="my-carousel-slide" v-for="(item, index) in props.list" :key="index" > <div class="item-carousel-content"> <div class="item" v-for="(ele, el_index) in item" :key="el_index"> <div class="pic"></div> <div class="item-name" :style="{ backgroundColor: ele.color }"> {{ ele.code }} </div> </div> </div> </q-carousel-slide> </q-carousel> </div> <div class="points"> <div class="cursor-pointer" :class="{ active: slide === String(index + 1) }" v-for="(i, index) in props.list" :key="index" @click="clickPoint(String(index + 1))" ></div> </div> </template> </div> </template> <style lang="scss" scoped> .my-carousel-box { width: 100%; height: 100%; display: flex; flex-flow: column nowrap; } .content { flex: 1; } .my-carousel { height: 100% !important; background-color: transparent; } .my-carousel-slide { padding: 0 !important; } .item-carousel-content { width: 100%; height: 100%; overflow: hidden; // 5列 * 2行 display: grid; grid-template-columns: repeat(5, 1fr); grid-template-rows: repeat(2, 1fr); // grid-template-columns: repeat(2, 1fr); // grid-template-rows: repeat(2, 1fr); grid-gap: 5px 5px; } .item { display: flex; flex-flow: column nowrap; .pic { width: 100%; background-image: url('https://img0.baidu.com/it/u=925843206,3288141497&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1666803600&t=81f620f962ec6a70673c05d6a55328b5'); background-size: 100% 100%; flex: 1; } .item-name { height: 30px; display: flex; justify-content: center; align-items: center; } } .points { padding: 5px; display: flex; flex-flow: row wrap; justify-content: center; align-items: center; } // 小圆点 .cursor-pointer { height: 4px; width: 40px; margin-right: 5px; border-radius: 50px; background-color: rgba($color: #3ecdff, $alpha: 0.3); cursor: pointer; transition: all 0.5s; } .active { background-color: #3ecdff; } </style>