123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- import request from '@/helpers/request'
- import { Icon, Toast, Uploader, Image } from 'vant'
- import { defineComponent } from 'vue'
- import styles from './index.module.less'
- import { useCustomFieldValue } from '@vant/use'
- import { browser } from '@/helpers/utils'
- import iconUploader from '@common/images/icon_uploader_video.png'
- import { postMessage } from '@/helpers/native-message'
- export default defineComponent({
- name: 'ColUploadVideo',
- props: {
- modelValue: String,
- posterUrl: String,
- tips: {
- type: String,
- default: '点击上传'
- },
- nativeUpload: {
- // 是否使用原生上传, 且当前环境为app才会生效
- type: Boolean,
- default: true
- },
- size: {
- type: Number,
- default: 30
- },
- deletable: {
- type: Boolean,
- default: true
- }
- },
- data() {
- return {
- posterUrlInner: ''
- }
- },
- async mounted() {
- if (this.modelValue) {
- const urlImg = await this.getVideoBase64(this.modelValue)
- this.posterUrlInner = urlImg as string
- this.$emit('update:posterUrl', urlImg as string)
- }
- this.posterUrlInner = this.posterUrlInner || this.posterUrl || ''
- },
- methods: {
- beforeRead(file: any) {
- const isLt2M = file.size / 1024 / 1024 < this.size
- console.log(this.size)
- if (!isLt2M) {
- Toast(`上传视频大小不能超过 ${this.size}MB`)
- return false
- }
- return true
- },
- beforeDelete(file: any, detail: { index: any }) {
- // this.dataModel.splice(detail.index, 1)
- return true
- },
- async afterRead(file: any, detail: any) {
- try {
- file.status = 'uploading'
- file.message = '上传中...'
- let formData = new FormData()
- formData.append('file', file.file)
- let res = await request.post('/api-teacher/uploadFile', {
- data: formData
- })
- const url = res.data.url
- const urlImg = await this.getVideoBase64(url)
- this.posterUrlInner = urlImg as string
- this.$emit('update:modelValue', url)
- this.$emit('update:posterUrl', urlImg as string)
- } catch (error) {
- //
- }
- },
- onClose(e: any) {
- this.posterUrlInner = ''
- this.$emit('update:modelValue', null)
- e.stopPropagation()
- },
- onNativeUpload() {
- postMessage(
- { api: 'chooseFile', content: { type: 'video' } },
- (res: any) => {
- this.posterUrlInner = res.firstFrameImg
- this.$emit('update:modelValue', res.fileUrl)
- this.$emit('update:posterUrl', res.firstFrameImg)
- }
- )
- },
- getVideoBase64(url: string) {
- return new Promise(function (resolve) {
- let dataURL = ''
- const video = document.createElement('video')
- video.setAttribute('crossOrigin', 'anonymous') // 处理跨域
- video.setAttribute('src', url)
- video.setAttribute('preload', 'auto')
- video.addEventListener('loadeddata', function () {
- const canvas = document.createElement('canvas')
- console.log('video.clientWidth', video.videoWidth) // 视频宽
- console.log('video.clientHeight', video.videoHeight) // 视频高
- const width = video.videoWidth || 750 // canvas的尺寸和图片一样
- const height = video.videoHeight || 500 // 设置默认宽高为 750 * 500
- canvas.width = width
- canvas.height = height
- ;(canvas as any)
- .getContext('2d')
- .drawImage(video, 0, 0, width, height) // 绘制canvas
- dataURL = canvas.toDataURL('image/jpeg') // 转换为base64
- resolve(dataURL)
- })
- })
- }
- },
- render() {
- useCustomFieldValue(() => this.modelValue)
- return (
- <div class={styles['uploader-section']}>
- {this.modelValue && this.deletable ? (
- <Icon
- name="cross"
- onClick={this.onClose}
- class={styles['img-close']}
- />
- ) : null}
- {browser().isApp && this.nativeUpload ? (
- <div onClick={this.onNativeUpload} style={{ height: '100%' }}>
- {this.modelValue ? (
- <video
- ref="videoUpload"
- class={styles.uploadImg}
- src={this.modelValue}
- poster={this.posterUrlInner}
- />
- ) : (
- <div class={styles.uploader}>
- <Icon name={iconUploader} size="32" />
- <p class={styles.uploaderText}>{this.tips}</p>
- </div>
- )}
- </div>
- ) : (
- <>
- {/* @ts-ignore */}
- <Uploader
- accept=".mp4"
- afterRead={this.afterRead}
- beforeRead={this.beforeRead}
- beforeDelete={this.beforeDelete}
- v-slots={{
- default: () =>
- this.modelValue ? (
- <video
- ref="videoUpload"
- class={styles.uploadImg}
- src={this.modelValue}
- poster={this.posterUrlInner}
- />
- ) : (
- <div class={styles.uploader}>
- <Icon name={iconUploader} size="32" />
- <p class={styles.uploaderText}>{this.tips}</p>
- </div>
- )
- }}
- />
- </>
- )}
- </div>
- )
- }
- })
|