<!--
图片预览对话框组件

@description 用于预览单张或多张图片的弹窗组件，支持两种模式：
    1. URL模式：直接传入图片URL列表进行预览
    2. ID模式：传入图片ID列表，组件内部调用API获取图片base64编码，并展示

@props
    isShow: boolean - 控制对话框显示/隐藏
    type: 'url' | 'id' - 图片数据类型，url：直接使用URL，id：通过ID获取图片
    fileList: Array<{id: string}> - 图片文件ID列表（type为'id'时使用）
    imageList: string[] - 图片URL列表（type为'url'时使用）
    top: string - 对话框距离顶部距离，默认'10vh'
    width: string - 对话框宽度，默认'1200px'
    title: string - 对话框标题，默认'图片预览'

@emits
    update:isShow: (value: boolean) => void - 更新显示状态

@example
    1.URL模式
    <imagePreviewDialog
        v-model:isShow="showPreview"
        type="url"
        :imageList="['http://example.com/1.jpg', 'http://example.com/2.jpg']"
    />

    2.ID模式
    <imagePreviewDialog
        v-model:isShow="showPreview"
        type="id"
        :fileList="[{id: '123'}, {id: '456'}]"
    />
-->
<template>
    <Dialog
        v-bind="attrs"
        v-model="isShowDialog"
        :width="width"
        :top="top"
        @open="open"
        @close="handleClose"
    >
        <div class="preview-container">
            <!-- 图片数量信息 -->
            <div class="image-preview-loading flex-center" v-if="imageLoading">
                <el-progress
                    :percentage="50"
                    :stroke-width="15"
                    striped
                    :indeterminate="true"
                    :show-text="false"
                />
            </div>
            <template v-else="imageLoading">
                <div class="file-preview-container flex-center">
                    <!-- 主图片显示区域 -->
                    <div class="main-image-container" v-if="!imageLoading && imgUrls.length > 0">
                        <el-image
                            :src="imgUrls[currentIndex]"
                            :preview-src-list="imgUrls"
                            :initial-index="currentIndex"
                            fit="contain"
                            class="main-image"
                        />

                        <!-- 图片导航按钮 -->
                        <div class="image-nav" v-if="imgUrls.length > 1">
                            <el-button
                                @click="prevImage"
                                :disabled="currentIndex === 0"
                                circle
                                class="nav-btn prev-btn"
                            >
                                <el-icon><ArrowLeft /></el-icon>
                            </el-button>
                            <span class="nav-info"
                                >{{ currentIndex + 1 }} / {{ imgUrls.length }}</span
                            >
                            <el-button
                                @click="nextImage"
                                :disabled="currentIndex === imgUrls.length - 1"
                                circle
                                class="nav-btn next-btn"
                            >
                                <el-icon><ArrowRight /></el-icon>
                            </el-button>
                        </div>
                    </div>
                </div>

                <!-- 缩略图列表 -->
                <div class="thumbnail-container" v-if="!imageLoading && imgUrls.length > 1">
                    <div class="thumbnail-list">
                        <div
                            v-for="(url, index) in imgUrls"
                            :key="index"
                            :class="['thumbnail-item', { active: index === currentIndex }]"
                            @click="currentIndex = index"
                        >
                            <el-image :src="url" fit="cover" class="thumbnail-image" />
                            <div class="thumbnail-index">{{ index + 1 }}</div>
                        </div>
                    </div>
                </div>
            </template>
        </div>
    </Dialog>
</template>
<script lang="ts" setup name="imagePreviewDialog">
import { computed, defineProps, defineEmits, ref } from 'vue'
import { getImgUrlById } from '@/api/system/file'
import Dialog from '@/components/Dialog/index.vue'
import { ElMessage } from 'element-plus'
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue'
const props = defineProps({
    isShow: {
        type: Boolean,
        default: false
    },
    type: {
        type: String,
        default: 'url'
    },
    fileList: {
        type: Array,
        default: () => []
    },
    imageList: {
        type: Array as () => string[],
        default: () => []
    },
    top: {
        type: String,
        default: '10vh'
    },
    width: {
        type: String,
        default: '1200px'
    },
    title: {
        type: String,
        default: '图片预览'
    }
})
const emit = defineEmits(['update:isShow'])

const imgUrls = ref<string[]>([])
const currentIndex = ref(0)
const imageLoading = ref(false)

const isShowDialog = computed({
    get: () => {
        return props.isShow
    },
    set: (val) => {
        emit('update:isShow', val)
    }
})

const attrs = computed(() => {
    return {
        title: props.title
    }
})

const open = async () => {
    imageLoading.value = true
    currentIndex.value = 0 // 重置到第一张图片

    if (props.type === 'url') {
        imgUrls.value = props.imageList.map((item) => {
            return item
        })
        imageLoading.value = false
    } else {
        await getImageList()
        imageLoading.value = false
    }
}

const prevImage = () => {
    if (currentIndex.value > 0) {
        currentIndex.value--
    }
}

const nextImage = () => {
    if (currentIndex.value < imgUrls.value.length - 1) {
        currentIndex.value++
    }
}

const handleClose = () => {
    // 清空数据
    imgUrls.value = []
    currentIndex.value = 0
    imageLoading.value = false
}

async function getImageList() {
    const files = props.fileList as { id: string }[]
    const promises = files.map((file) => getImage(file.id))

    try {
        const urls = await Promise.all(promises)
        imgUrls.value = urls.filter((url) => url) // 过滤掉空值
    } catch (error) {
        console.error('加载图片失败:', error)
        ElMessage.error('图片加载失败')
    }
}

async function getImage(id: string): Promise<string> {
    if (!id) return ''

    try {
        const userPhotoData = (await getImgUrlById(id)) as any
        return userPhotoData || ''
    } catch (error) {
        console.error('获取图片失败:', error)
        return ''
    }
}
</script>
<style lang="scss" scoped>
.preview-container {
    width: 100%;
    height: 70vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 10px;
}

.image-preview-loading {
    width: 400px;
    height: 200px;
    .el-progress {
        width: 100%;
    }
}

.file-preview-container {
    flex: 1;
    height: calc(100% - 120px);
    display: flex;
    justify-content: center;
    align-items: center;
    position: relative;
}

.main-image-container {
    position: relative;
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
}

.main-image {
    height: 100%;
    width: 100%;
    cursor: pointer;
}

.image-nav {
    position: absolute;
    bottom: 10px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 10px;
    background: rgba(0, 0, 0, 0.7);
    padding: 8px 16px;
    border-radius: 20px;
    color: white;
}

.nav-btn {
    width: 32px;
    height: 32px;
}

.nav-info {
    font-size: 14px;
    min-width: 60px;
    text-align: center;
}

.thumbnail-container {
    width: 100%;
}

.thumbnail-list {
    display: flex;
    gap: 8px;
    padding: 0 10px;
    width: 100%;
    overflow-x: auto;
}

.thumbnail-item {
    position: relative;
    width: 80px;
    height: 80px;
    border: 2px solid transparent;
    border-radius: 4px;
    cursor: pointer;
    transition: border-color 0.3s;
    box-sizing: border-box;

    &.active {
        border-color: #409eff;
    }

    &:hover {
        border-color: #79bbff;
    }
}

.thumbnail-image {
    width: 100%;
    height: 100%;
    border-radius: 2px;
}

.thumbnail-index {
    position: absolute;
    top: 2px;
    right: 2px;
    background: rgba(0, 0, 0, 0.7);
    color: white;
    font-size: 12px;
    padding: 2px 4px;
    border-radius: 2px;
    min-width: 16px;
    text-align: center;
}
</style>
