index.tsx 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. import request from '@/helpers/request'
  2. import { Icon, Toast, Uploader, Image } from 'vant'
  3. import { defineComponent } from 'vue'
  4. import styles from './index.module.less'
  5. import { useCustomFieldValue } from '@vant/use'
  6. import { browser } from '@/helpers/utils'
  7. import umiRequest from 'umi-request'
  8. import iconUploader from '@common/images/icon_uploader_video.png'
  9. import iconUploadPoster from '@common/images/icon_upload_poster.png'
  10. import { postMessage } from '@/helpers/native-message'
  11. import { getOssUploadUrl, state } from '@/state'
  12. import { getUploadSign, onOnlyFileUpload } from '@/helpers/oss-file-upload'
  13. export default defineComponent({
  14. name: 'ColUploadVideo',
  15. props: {
  16. modelValue: String,
  17. posterUrl: String,
  18. tips: {
  19. type: String,
  20. default: '点击上传'
  21. },
  22. nativeUpload: {
  23. // 是否使用原生上传, 且当前环境为app才会生效
  24. type: Boolean,
  25. default: true
  26. },
  27. size: {
  28. type: Number,
  29. default: 30
  30. },
  31. deletable: {
  32. type: Boolean,
  33. default: true
  34. },
  35. bucket: {
  36. type: String,
  37. default: 'daya'
  38. }
  39. },
  40. methods: {
  41. beforeRead(file: any) {
  42. const isLt2M = file.size / 1024 / 1024 < this.size
  43. // console.log(this.size)
  44. if (!isLt2M) {
  45. Toast(`上传视频大小不能超过 ${this.size}MB`)
  46. return false
  47. }
  48. return true
  49. },
  50. beforeDelete(file: any, detail: { index: any }) {
  51. // this.dataModel.splice(detail.index, 1)
  52. return true
  53. },
  54. async afterRead(file: any, detail: any) {
  55. try {
  56. file.status = 'uploading'
  57. file.message = '上传中...'
  58. // 获取签名
  59. // const signUrl =
  60. // state.platformType === 'TEACHER'
  61. // ? '/api-teacher/getUploadSign'
  62. // : '/api-student/getUploadSign'
  63. const fileName = file.file.name.replaceAll(' ', '_')
  64. const key = new Date().getTime() + fileName
  65. console.log(file)
  66. // const res = await request.post(signUrl, {
  67. // data: {
  68. // filename: fileName,
  69. // bucketName: this.bucket,
  70. // postData: {
  71. // filename: fileName,
  72. // acl: 'public-read',
  73. // key: key
  74. // }
  75. // }
  76. // })
  77. const { data } = await getUploadSign({
  78. filename: key,
  79. bucketName: this.bucket,
  80. postData: {
  81. filename: key,
  82. acl: 'public-read',
  83. key: key
  84. }
  85. })
  86. Toast.loading({
  87. message: '加载中...',
  88. forbidClick: true,
  89. loadingType: 'spinner',
  90. duration: 0
  91. })
  92. const obj = {
  93. policy: data.policy,
  94. signature: data.signature,
  95. key: key,
  96. KSSAccessKeyId: data.kssAccessKeyId,
  97. acl: 'public-read',
  98. name: key,
  99. file: file.file
  100. }
  101. const uploadUrl = await onOnlyFileUpload(
  102. getOssUploadUrl(this.bucket),
  103. obj
  104. )
  105. // const formData = new FormData()
  106. // for (const key in obj) {
  107. // formData.append(key, obj[key])
  108. // }
  109. // formData.append('file', file.file)
  110. // await umiRequest(getOssUploadUrl(this.bucket), {
  111. // method: 'POST',
  112. // data: formData
  113. // })
  114. // const uploadUrl = getOssUploadUrl(this.bucket) + key
  115. Toast.clear()
  116. this.$emit('update:modelValue', uploadUrl)
  117. // this.onUploadChange(uploadUrl)
  118. // let formData = new FormData()
  119. // formData.append('file', file.file)
  120. // let res = await request.post('/api-teacher/uploadFile', {
  121. // data: formData
  122. // })
  123. // const url = res.data.url
  124. // this.$emit('update:modelValue', uploadUrl)
  125. } catch (error) {
  126. //
  127. console.log(error)
  128. }
  129. },
  130. onClose(e: any) {
  131. this.$emit('update:modelValue', null)
  132. e.stopPropagation()
  133. },
  134. onNativeUpload() {
  135. postMessage(
  136. { api: 'chooseFile', content: { type: 'video', bucket: this.bucket } },
  137. (res: any) => {
  138. // this.posterUrlInner = res.firstFrameImg
  139. this.$emit('update:modelValue', res.fileUrl)
  140. // this.$emit('update:posterUrl', res.firstFrameImg)
  141. }
  142. )
  143. },
  144. getVideoBase64(url: string) {
  145. return new Promise(function (resolve) {
  146. let dataURL = ''
  147. const video = document.createElement('video')
  148. video.setAttribute('crossOrigin', 'anonymous') // 处理跨域
  149. video.setAttribute('src', url)
  150. video.setAttribute('preload', 'auto')
  151. video.addEventListener('loadeddata', function () {
  152. console.log(video, 'video loadeddata')
  153. const canvas = document.createElement('canvas')
  154. console.log('video.clientWidth', video.videoWidth) // 视频宽
  155. console.log('video.clientHeight', video.videoHeight) // 视频高
  156. const width = video.videoWidth || 750 // canvas的尺寸和图片一样
  157. const height = video.videoHeight || 500 // 设置默认宽高为 750 * 500
  158. canvas.width = width
  159. canvas.height = height
  160. ;(canvas as any)
  161. .getContext('2d')
  162. .drawImage(video, 0, 0, width, height) // 绘制canvas
  163. dataURL = canvas.toDataURL('image/jpeg') // 转换为base64
  164. resolve(dataURL)
  165. })
  166. })
  167. }
  168. },
  169. render() {
  170. useCustomFieldValue(() => this.modelValue)
  171. return (
  172. <div class={styles['uploader-section']}>
  173. {this.modelValue && this.deletable ? (
  174. <Icon
  175. name="cross"
  176. onClick={this.onClose}
  177. class={styles['img-close']}
  178. />
  179. ) : null}
  180. {browser().isApp && this.nativeUpload ? (
  181. <div onClick={this.onNativeUpload} style={{ height: '100%' }}>
  182. {this.modelValue ? (
  183. <video
  184. ref="videoUpload"
  185. class={styles.uploadImg}
  186. src={this.modelValue + '#t=1,4'}
  187. // poster={iconUploadPoster}
  188. />
  189. ) : (
  190. <div class={styles.uploader}>
  191. <Icon name={iconUploader} size="32" />
  192. <p class={styles.uploaderText}>{this.tips}</p>
  193. </div>
  194. )}
  195. </div>
  196. ) : (
  197. <>
  198. {/* @ts-ignore */}
  199. <Uploader
  200. accept=".mp4"
  201. afterRead={this.afterRead}
  202. beforeRead={this.beforeRead}
  203. beforeDelete={this.beforeDelete}
  204. v-slots={{
  205. default: () =>
  206. this.modelValue ? (
  207. <video
  208. ref="videoUpload"
  209. class={styles.uploadImg}
  210. src={this.modelValue + '#t=1,4'}
  211. // poster={this.posterUrl || ''}
  212. />
  213. ) : (
  214. <div class={styles.uploader}>
  215. <Icon name={iconUploader} size="32" />
  216. <p class={styles.uploaderText}>{this.tips}</p>
  217. </div>
  218. )
  219. }}
  220. />
  221. </>
  222. )}
  223. </div>
  224. )
  225. }
  226. })