vue3+ts+alioss+elementplus文件上传组件封装

<template>
  <div style="width: 500px">
    <el-upload
      class="upload-demo"
      multiple
      :accept="fileType"
      :limit="limitNum"
      :show-file-list="false"
      :http-request="uploadRequest"
    >
      <el-button type="primary">Click to upload</el-button>
      <template #tip>
        <div class="el-upload__tip">提示:只支持上传{{ tip }}格式文件</div>
        <div class="fileList" v-show="fileData !== ''">
          <div style="display: flex; vertical-align: middle">
            <el-icon style="margin: 8px"><Document /></el-icon>
            <div
              class="fileName"
              style="font-size: 12px; width: 500; overflow: hidden"
            >
              <el-tooltip
                class="box-item"
                effect="dark"
                content="点击此处将打开预览文件"
                placement="top"
              >
                <span class="text" @click="previewFile">
                  {{ fileData }}
                </span>
              </el-tooltip>
            </div>
            <el-tooltip
              class="box-item"
              effect="dark"
              content="点击删除"
              placement="top"
            >
              <el-icon
                class="icon_del"
                style="margin: 8px"
                v-show="fileData"
                @click.stop="deleteFile"
              >
                <Delete />
              </el-icon>
            </el-tooltip>
          </div>
        </div>
      </template>
    </el-upload>
    <!-- 预览弹框 -->
    <el-dialog
      v-model="dialogVisible"
      title="预览"
      width="40%"
      height="30vh"
      :before-close="handleClose"
      :close-on-click-modal="false"
      :destroy-on-close="true"
    >
      <div v-if="fileData.includes('mp3')">
        <audio style="width: 100%" controls :src="fileData"></audio>
      </div>
      <div v-else-if="fileData.includes('mp4')">
        <video style="width: 100%" controls :src="fileData"></video>
      </div>
    </el-dialog>
  </div>
</template>
<script lang="ts" setup>
import { ref, watchEffect } from 'vue'
import { reqAliOssUpload } from '@/api/aliOSS'
import axios from 'axios'

const props = defineProps({
  modelValue: {
    type: Array,
    default: Array,
  },
  fileType: {
    type: String,
    default: 'image/*,video/*',
  },
  reqUrl: {
    type: Number,
    default: null,
  },
  reqType: {
    type: String,
    default: '',
  },
  reqCategory: {
    type: String,
    default: '',
  },
  limitNum: {
    type: Number,
    default: 4,
  },
  tip: {
    type: String,
    default: '音频',
  },
})

const filesArray = ref()

//声明事件消息
const emits = defineEmits<{
  (e: 'update:modelValue', value: string): void
}>()

//保存图片内存临时地址
const fileData = ref('')
watchEffect(() => {
  fileData.value = props.modelValue as any
})

const uploadRequest = async (file: any) => {
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  const res = await reqAliOssUpload(props.reqUrl, {
    category: props.reqCategory,
    mediaType: props.reqType,
  })
  const data = res.data
  // 随机数
  const random = Math.floor(Math.random() * 10000)
  // 文件后缀
  const fileSuffix = file.file.name.split('.').pop()
  const params = {
    key: data.dir + `${Date.now()}_${random}.${fileSuffix}`,
    policy: data.policy,
    OSSAccessKeyId: data.accessid,
    success_action_status: '200',
    signature: data.signature,
    file: file.file,
  }
  const url = 'https://' + data.host
  const config = {
    headers: {
      'Content-Type': 'multipart/form-data',
      'Access-Control-Allow-Origin': '*',
    },
  }
  const uploadRes = await axios.post(url, params, config)
  console.log('uploadRes', uploadRes)
  const filePath = 'https://' + data.host + '/' + params.key
  filesArray.value = filePath
  emits('update:modelValue', filePath)
}

// 删除文件
const deleteFile = () => {
  emits('update:modelValue', '')
}

// 预览文件
const dialogVisible = ref(false)
const previewFile = (e: any) => {
  console.log('预览', e)
  dialogVisible.value = true
}
// 关闭bofang
const handleClose = () => {
  dialogVisible.value = false
  // 销毁弹框组件
}
</script>

<style lang="scss">
.fileList {
  // 鼠标移入背景变色且字体变色
  &:hover {
    background-color: #f5f7fa;
  }
  .icon_del {
    &:hover {
      color: #ef1e1e;
      cursor: pointer;
    }
  }
  .fileName {
    // 鼠标移入字体变色
    .text {
      &:hover {
        color: #409eff;
        text-decoration: underline;
        cursor: pointer;
      }
    }
  }
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值