<template> 
 | 
    <div class="preview"> 
 | 
        <div class="preview_close" @click="closes"> 
 | 
            <van-icon name="cross" size="20" /> 
 | 
        </div> 
 | 
        <div class="preview_content"> 
 | 
            <Swiper @slideChange="onSlideChange" :initialSlide="props.index"> 
 | 
                <SwiperSlide v-for="(item, index) in props.list" :key="index"> 
 | 
                    <div class="preview_content_box"> 
 | 
                        <img v-if="item.type === 0" :src="item.url" alt="" /> 
 | 
                        <video ref="video" v-else-if="item.type === 1" :src="item.url" controls="controls"></video> 
 | 
                    </div> 
 | 
                </SwiperSlide> 
 | 
            </Swiper> 
 | 
        </div> 
 | 
    </div> 
 | 
</template> 
 | 
  
 | 
<script setup lang="ts"> 
 | 
    import { ref, defineProps, defineEmits } from 'vue' 
 | 
    import { Swiper, SwiperSlide } from 'swiper/vue' 
 | 
    import 'swiper/css' 
 | 
    import 'swiper/css/effect-cube' 
 | 
    import 'swiper/css/pagination' 
 | 
  
 | 
    const props = defineProps({ 
 | 
        list: { 
 | 
            type: Array, 
 | 
            require: true 
 | 
        }, 
 | 
        index: { 
 | 
            type: Number, 
 | 
            default: 0 
 | 
        } 
 | 
    }) 
 | 
  
 | 
    let video: any = ref(null) 
 | 
  
 | 
    const emit = defineEmits([ 'close' ]) 
 | 
  
 | 
    // 关闭组件 
 | 
    const closes = () => { 
 | 
        emit('close') 
 | 
    } 
 | 
  
 | 
    // 切换暂停播放 
 | 
    const onSlideChange = () => { 
 | 
        if (!video.value) return 
 | 
        video.value.forEach((item: any) => { 
 | 
            item.pause() 
 | 
        }) 
 | 
    } 
 | 
</script> 
 | 
  
 | 
<style lang="scss" scoped> 
 | 
.preview { 
 | 
    position: fixed; 
 | 
    top: 0; 
 | 
    left: 0; 
 | 
    width: 100%; 
 | 
    height: 100%; 
 | 
    background: rgba(0, 0, 0, 0.8); 
 | 
    z-index: 9999; 
 | 
    .preview_close { 
 | 
        position: fixed; 
 | 
        right: 50px; 
 | 
        top: 50px; 
 | 
        width: 70px; 
 | 
        height: 70px; 
 | 
        border-radius: 50%; 
 | 
        background: #B2B2B2; 
 | 
        display: flex; 
 | 
        align-items: center; 
 | 
        justify-content: center; 
 | 
        z-index: 99999; 
 | 
    } 
 | 
    .preview_content { 
 | 
        height: 100%; 
 | 
        position: relative; 
 | 
        top: 50%; 
 | 
        left: 0; 
 | 
        transform: translate(0, -50%); 
 | 
        .swiper { 
 | 
            width: 100%; 
 | 
            height: 100%; 
 | 
            display: flex; 
 | 
            align-items: center; 
 | 
            justify-content: center; 
 | 
            .swiper-slide { 
 | 
                width: 100%; 
 | 
                height: 100%; 
 | 
                position: relative; 
 | 
                .preview_content_box { 
 | 
                    width: 100%; 
 | 
                    position: absolute; 
 | 
                    top: 50%; 
 | 
                    left: 50%; 
 | 
                    transform: translate(-50%, -50%); 
 | 
                    display: flex; 
 | 
                    align-items: center; 
 | 
                    justify-content: center; 
 | 
                    img { 
 | 
                        width: 100%; 
 | 
                    } 
 | 
                    video { 
 | 
                        width: 100%; 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
} 
 | 
</style> 
 |