123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- <template>
- <el-button type="primary" :loading="loading" v-if="!src">
- <label class="file" for="file"> 上传素材 </label>
- <input
- style="display: none"
- @change="chagne"
- type="file"
- name="file"
- accept="image/*,video/*"
- id="file"
- />
- </el-button>
- <!-- 文件上传 图片 视频 -->
- <div v-else class="media-components">
- <svg
- t="1732589883711"
- class="close"
- viewBox="0 0 1024 1024"
- version="1.1"
- xmlns="http://www.w3.org/2000/svg"
- @click="close"
- width="16"
- height="16"
- >
- <path
- d="M548.992 503.744L885.44 167.328a31.968 31.968 0 1 0-45.248-45.248L503.744 458.496 167.328 122.08a31.968 31.968 0 1 0-45.248 45.248l336.416 336.416L122.08 840.16a31.968 31.968 0 1 0 45.248 45.248l336.416-336.416L840.16 885.44a31.968 31.968 0 1 0 45.248-45.248L548.992 503.744z"
- p-id="4267"
- />
- </svg>
- <el-image style="width: 120px; height: 120px" :src="src" fit="contain" />
- <svg
- t="1732603337032"
- v-if="fileType === 'video'"
- class="play"
- viewBox="0 0 1024 1024"
- version="1.1"
- xmlns="http://www.w3.org/2000/svg"
- p-id="5375"
- width="32"
- height="32"
- @click="playVideo"
- >
- <path
- d="M512 0C230.4 0 0 230.4 0 512s230.4 512 512 512 512-230.4 512-512S793.6 0 512 0z m0 981.333333C253.866667 981.333333 42.666667 770.133333 42.666667 512S253.866667 42.666667 512 42.666667s469.333333 211.2 469.333333 469.333333-211.2 469.333333-469.333333 469.333333z"
- fill="#707070"
- p-id="5376"
- ></path>
- <path
- d="M672 441.6l-170.666667-113.066667c-57.6-38.4-106.666667-12.8-106.666666 57.6v256c0 70.4 46.933333 96 106.666666 57.6l170.666667-113.066666c57.6-42.666667 57.6-106.666667 0-145.066667z"
- fill="#707070"
- p-id="5377"
- ></path>
- </svg>
- </div>
- </template>
- <script setup lang="ts">
- import { uploadMaterial } from '@/api/index'
- // 获取组件传参
- import { ElMessage } from 'element-plus'
- import { defineProps, ref } from 'vue'
- // 传参父组件
- const emit = defineEmits(['change', 'getCalc'])
- const props = defineProps<{ src: string }>()
- const loading = ref(false)
- const src = ref(props.src)
- const fileType = ref('')
- const isImg = (url: string) => {
- return /\.(jpg|jpeg|png|gif)$/.test(url)
- }
- // 判定如果是图片则直接输出图片,如果是视频则输出第一帧图片
- const getImage = (file: File | string) => {
- const video = document.createElement('video')
- fileType.value = 'video'
- if (typeof file === 'string') {
- video.setAttribute('crossorigin', 'anonymous')
- video.src = file
- } else {
- if (file.type.indexOf('image') !== -1) {
- src.value = URL.createObjectURL(file)
- fileType.value = 'image'
- const img = new Image()
- img.onload = function () {
- emit('getCalc', img.width, img.height)
- }
- img.src = URL.createObjectURL(file)
- return
- }
- // 视频 获取第一帧
- // 播放本地视频文件
- video.src = URL.createObjectURL(file)
- }
- video.onloadeddata = function () {
- // 跳转到第二秒
- video.currentTime = 1
- // 当视频到达第二秒时,绘制帧
- video.addEventListener('seeked', () => {
- // 获取第一帧
- emit('getCalc', video.videoWidth, video.videoHeight)
- const canvas = document.createElement('canvas')
- canvas.width = video.videoWidth
- canvas.height = video.videoHeight
- const ctx = canvas.getContext('2d')
- ctx?.drawImage(video, 0, 0, video.videoWidth, video.videoHeight)
- src.value = canvas.toDataURL()
- })
- }
- }
- if (src.value) {
- const isImgUrl = isImg(src.value)
- fileType.value = isImgUrl ? 'image' : 'video'
- getImage(src.value)
- }
- let oriUrl = props.src ? props.src : ''
- let times = 0
- const close = () => {
- src.value = ''
- fileType.value = ''
- oriUrl = ''
- emit('getCalc', 0, 0)
- emit('change', '')
- }
- // 传参为文件
- const chagne = (e: Event) => {
- if (!e.target) return
- const inputElement = e.target as HTMLInputElement
- if (!inputElement.files || !inputElement.files.length) return
- loading.value = true
- // 上传文件获取地址后传出组件
- const file: File = inputElement.files[0]
- const formData = new FormData()
- formData.append('file', file)
- uploadMaterial(formData)
- .then(({ data }) => {
- ElMessage({
- message: '上传成功',
- type: 'success',
- })
- getImage(file)
- inputElement.value = ''
- times = 0
- oriUrl = data.url
- emit('change', oriUrl)
- loading.value = false
- })
- .catch(() => {
- if (times++ < 5) {
- ElMessage({
- message: '正在重新上传',
- type: 'info',
- })
- const t = setTimeout(function () {
- console.log(times)
- clearTimeout(t)
- chagne(e)
- }, 1000)
- } else {
- ElMessage({
- message: '网络有问题,请检查后重新上传',
- type: 'info',
- })
- inputElement.value = ''
- loading.value = false
- times = 0
- }
- })
- }
- const playVideo = () => {
- window.open(oriUrl)
- }
- </script>
- <style scoped>
- .media-components {
- border-radius: 4px;
- background: #fdfdfd;
- width: 120px;
- height: 120px;
- box-shadow: var(--el-box-shadow-lighter);
- position: relative;
- }
- .close {
- position: absolute;
- top: 10px;
- right: 10px;
- cursor: pointer;
- z-index: 10;
- }
- .play {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- z-index: 10;
- cursor: pointer;
- }
- </style>
|