<!-- PreviewBlock.vue - 预览模块 -->
<template>
  <div class="preview-block">
    <div v-if="showFileList && showFileList.length" class="preview-list">
      <div
        v-for="file in showFileList"
        :key="file.uid"
        class="preview-item"
      >
        <!-- 图片类型且为图片文件时显示预览图 -->
        <div v-if="type === 'image' && isImageFile(file)" class="preview-image">
          <el-image
            :src="file.fileUrl"
            :preview-src-list="getImageUrlList()"
            fit="cover"
            :initial-index="getImageIndex(file)"
          >
            <template #error>
              <div class="image-slot">
                <el-icon><Picture /></el-icon>
              </div>
            </template>
          </el-image>
        </div>
        <!-- 非图片或非图片类型显示图标 -->
        <div v-else class="preview-icon">
          <el-icon :size="40">
            <component :is="getFileIcon(file)" />
          </el-icon>
        </div>
        
        <!-- <div class="preview-info">
          <span class="file-name" :title="file.fileName">{{ file.fileName }}</span>
          <span class="file-size">{{ formatFileSize(file.fileSize) }}</span>
        </div> -->
        
        <div class="preview-actions" v-if="!readonly">
          <el-button
            type="danger"
            :icon="Delete"
            circle
            size="small"
            @click="handleRemove(file)"
          />
        </div>
      </div>
    </div>
    <!-- <div v-else class="preview-empty">
      <el-empty description="暂无文件" :image-size="80" />
    </div> -->
  </div>
</template>

<script setup>
import { computed } from 'vue'
import { Picture, Document, VideoCamera, Delete } from '@element-plus/icons-vue'

const props = defineProps({
  fileList: {
    type: Array,
    default: () => []
  },
  type: {
    type: String,
    default: 'image'
  },
  readonly: {
    type: Boolean,
    default: false
  }
})

const showFileList = computed(() => {
  if(!props.fileList?.length) return []
  if(props.type == 'image') return props.fileList.filter(file => isImageFile(file))
  if(props.type == 'video') return props.fileList.filter(file => isVideoFile(file))
})

const emit = defineEmits(['update:fileList'])

// 判断是否为图片文件
const isImageFile = (file) => {
  // 根据url后缀判断
  const imageExtensions = /\.(jpg|jpeg|png|gif|webp|bmp|svg)$/i
  if (file.fileUrl && imageExtensions.test(file.fileUrl)) return true
  // 根据文件类型判断
  if (file.type && file.type.startsWith('image/')) return true
  return false
}

const isVideoFile = (file) => {
  // 根据url后缀判断
  const videoExtensions = /\.(mp4|avi|mov|wmv|flv|mkv)$/i
  if (file.fileUrl && videoExtensions.test(file.fileUrl)) return true
}

// 获取所有图片的URL列表（用于预览）
const getImageUrlList = () => {
  return props.fileList
    .filter(file => isImageFile(file))
    .map(file => file.fileUrl)
}

// 获取当前图片在预览列表中的索引
const getImageIndex = (currentFile) => {
  const imageUrls = getImageUrlList()
  return imageUrls.findIndex(url => url === currentFile.fileUrl)
}

// 根据文件类型获取对应图标
const getFileIcon = (file) => {
  const ext = file.fileName?.split('.').pop()?.toLowerCase() || ''
  
  // 视频文件
  if (['mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv'].includes(ext)) {
    return VideoCamera
  }
  // 音频文件
  if (['mp3', 'wav', 'flac', 'aac', 'ogg'].includes(ext)) {
    return VideoCamera
  }
  // 默认文档图标
  return Document
}

// 格式化文件大小
const formatFileSize = (size) => {
  if (!size) return ''
  if (size < 1024) return size + ' B'
  if (size < 1024 * 1024) return (size / 1024).toFixed(2) + ' KB'
  return (size / (1024 * 1024)).toFixed(2) + ' MB'
}

// 删除文件
const handleRemove = (file) => {
  const index = props.fileList.findIndex(item => item.fileUrl === file.fileUrl)
  emit('update:fileList', [...props.fileList.slice(0, index), ...props.fileList.slice(index + 1)] )
}
</script>

<style scoped>
.preview-block {
  width: 100%;
}

.preview-list {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-top: 16px;
}

.preview-item {
  position: relative;
  width: 120px;
  border: 1px solid #ebebeb;
  border-radius: 8px;
  overflow: hidden;
  transition: all 0.3s;
  background: #fafafa;
}

.preview-item:hover {
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}

.preview-image {
  width: 120px;
  height: 120px;
  overflow: hidden;
}

.preview-image :deep(.el-image) {
  width: 100%;
  height: 100%;
}

.preview-image :deep(.el-image__inner) {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.image-slot {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f5f7fa;
  color: #909399;
}

.preview-icon {
  width: 120px;
  height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f5f7fa;
  color: #409eff;
}

.preview-info {
  padding: 8px;
  text-align: center;
  border-top: 1px solid #ebebeb;
  background: white;
}

.file-name {
  display: block;
  font-size: 12px;
  color: #606266;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-size {
  display: block;
  font-size: 10px;
  color: #909399;
  margin-top: 4px;
}

.preview-actions {
  position: absolute;
  top: 4px;
  right: 4px;
  opacity: 0;
  transition: opacity 0.3s;
}

.preview-item:hover .preview-actions {
  opacity: 1;
}

.preview-empty {
  padding: 40px 0;
}
</style>