<template>
  <div class="attachment-upload">
    <el-upload
      :action="uploadUrl"
      :headers="headers"
      :data="uploadData"
      :show-file-list="false"
      :on-success="handleUploadSuccess"
      :on-error="handleUploadError"
      :before-upload="beforeUpload"
      :accept="accept"
      :multiple="multiple"
      :disabled="disabled"
      :loading="uploading"
    >
      <el-button :type="buttonType" :size="buttonSize" :icon="buttonIcon" :disabled="disabled">
        {{ buttonText }}
      </el-button>
    </el-upload>
    
    <div v-if="fileList.length > 0" class="file-list">
      <div v-for="(file, index) in fileList" :key="index" class="file-item">
        <div class="file-preview">
          <img v-if="isImageFile(file.url)" :src="file.url" class="file-image" />
          <div v-else class="file-icon">
            <i class="el-icon-document"></i>
          </div>
        </div>
        <div class="file-info">
          <div class="file-name">{{ file.name }}</div>
          <div class="file-size">{{ formatFileSize(file.size) }}</div>
        </div>
        <div class="file-actions">
          <el-button type="text" size="mini" @click="previewFile(file)">预览</el-button>
          <el-button type="text" size="mini" @click="downloadFile(file)">下载</el-button>
          <el-button type="text" size="mini" @click="removeFile(index)" style="color: #f56c6c;">删除</el-button>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'AttachmentUpload',
  props: {
    // 上传地址
    uploadUrl: {
      type: String,
      default: '/common/upload'
    },
    // 请求头
    headers: {
      type: Object,
      default: () => ({})
    },
    // 上传时附带的额外参数
    uploadData: {
      type: Object,
      default: () => ({})
    },
    // 接受上传的文件类型
    accept: {
      type: String,
      default: '*'
    },
    // 是否支持多选文件
    multiple: {
      type: Boolean,
      default: true
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      default: false
    },
    // 按钮类型
    buttonType: {
      type: String,
      default: 'primary'
    },
    // 按钮大小
    buttonSize: {
      type: String,
      default: 'mini'
    },
    // 按钮图标
    buttonIcon: {
      type: String,
      default: 'el-icon-upload'
    },
    // 按钮文字
    buttonText: {
      type: String,
      default: '上传文件'
    },
    // 文件列表
    value: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      uploading: false,
      fileList: []
    }
  },
  watch: {
    value: {
      handler(newVal) {
        this.fileList = [...newVal];
      },
      immediate: true
    }
  },
  methods: {
    // 上传前校验
    beforeUpload(file) {
      // 文件大小限制 (10MB)
      const isLt10M = file.size / 1024 / 1024 < 10;
      if (!isLt10M) {
        this.$message.error('上传文件大小不能超过 10MB!');
        return false;
      }
      
      this.uploading = true;
      return true;
    },
    
    // 上传成功
    handleUploadSuccess(response, file) {
      this.uploading = false;
      
      if (response.code === 200) {
        const fileInfo = {
          name: file.name,
          url: response.data.url,
          size: file.size,
          type: file.type
        };
        
        this.fileList.push(fileInfo);
        this.$emit('input', this.fileList);
        this.$emit('success', fileInfo);
        
        this.$message.success('上传成功');
      } else {
        this.$message.error(response.msg || '上传失败');
      }
    },
    
    // 上传失败
    handleUploadError(err, file) {
      this.uploading = false;
      this.$message.error('上传失败');
      this.$emit('error', err, file);
    },
    
    // 预览文件
    previewFile(file) {
      if (this.isImageFile(file.url)) {
        // 图片预览
        this.$alert(`<img src="${file.url}" style="max-width: 100%;" />`, '文件预览', {
          dangerouslyUseHTMLString: true,
          showConfirmButton: false,
          customClass: 'preview-dialog'
        });
      } else {
        // 其他文件类型，提供下载链接
        window.open(file.url, '_blank');
      }
    },
    
    // 下载文件
    downloadFile(file) {
      const link = document.createElement('a');
      link.href = file.url;
      link.download = file.name;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    },
    
    // 删除文件
    removeFile(index) {
      this.fileList.splice(index, 1);
      this.$emit('input', this.fileList);
      this.$emit('remove', index);
    },
    
    // 判断是否为图片文件
    isImageFile(url) {
      if (!url) return false;
      const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp'];
      return imageExtensions.some(ext => url.toLowerCase().includes(ext));
    },
    
    // 格式化文件大小
    formatFileSize(bytes) {
      if (bytes === 0) return '0 B';
      const k = 1024;
      const sizes = ['B', 'KB', 'MB', 'GB'];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }
  }
}
</script>

<style scoped>
.attachment-upload {
  width: 100%;
}

.file-list {
  margin-top: 15px;
}

.file-item {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
  padding: 10px;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  background-color: #fafafa;
}

.file-preview {
  margin-right: 15px;
}

.file-image {
  width: 60px;
  height: 60px;
  object-fit: cover;
  border-radius: 4px;
}

.file-icon {
  width: 60px;
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #f5f7fa;
  border-radius: 4px;
  color: #909399;
}

.file-icon i {
  font-size: 24px;
}

.file-info {
  flex: 1;
  margin-right: 15px;
}

.file-name {
  font-size: 14px;
  color: #303133;
  margin-bottom: 5px;
  word-break: break-all;
}

.file-size {
  font-size: 12px;
  color: #909399;
}

.file-actions {
  display: flex;
  gap: 5px;
}

/* 预览对话框样式 */
:deep(.preview-dialog) {
  width: 80%;
  max-width: 800px;
}

:deep(.preview-dialog .el-message-box__content) {
  text-align: center;
}
</style>
