submitVideo.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. <template>
  2. <view class="task-form-item form-item-media">
  3. <view class="form-lable">
  4. <text><text class="form-must" v-if="rule && rule.required">* </text>视频:</text>
  5. <text class="form-media-num">({{videos.length}}/{{num}})</text>
  6. </view>
  7. <view class="form-img-video">
  8. <view v-if="videos.length < num " class="updata-btn img-video-item" @click.stop="onChooseVideo()">
  9. <text class="iconfont_yige">&#xe69f;</text>
  10. <text>请上传视频</text>
  11. </view>
  12. <!-- <view class="img-video-box img-video-item" v-for="(item , index) in photos_list"
  13. @click.stop="onBigImg(index)">
  14. <view class="del-img-video iconfont_yige" @click.stop="delphotos(index)" v-if="!checkPage">&#xe867;
  15. </view>
  16. <image class="img-video" :src="item" mode="aspectFit"></image>
  17. </view> -->
  18. <view class="img-video-box img-video-item" v-for="(item,index) in videos" :key="`video_${index}`"
  19. @click.stop="onplay(item)">
  20. <view class="del-img-video iconfont_yige" v-if="!checkPage" @click.stop="delVldeo(index)">&#xe867;
  21. </view>
  22. <image class="img-video" :src="item + '?x-oss-process=video/snapshot,t_0,f_jpg'" mode="aspectFit" />
  23. </view>
  24. </view>
  25. <uni-popup ref="videoPlayRef" maskBg="rgba(0, 0, 0,.7)" @change="popupChange">
  26. <view class="video-play" style="width: 100vw;">
  27. <video autoplay v-if="playVideoUrl" style="width: 100%;max-height: 60vh;" :src="playVideoUrl" />
  28. </view>
  29. </uni-popup>
  30. </view>
  31. </template>
  32. <script>
  33. import {
  34. getcheckBigFile_Api,
  35. setUpload_tag_Api,
  36. getMargeTag_Api
  37. } from "@/api/task.js"
  38. import { getFileMd5 } from "@/utils/tool.js"
  39. export default {
  40. name: 'submitVideo',
  41. model: {
  42. prop: ['videos'],
  43. event: ['onChange']
  44. },
  45. props: {
  46. checkPage: {
  47. type: Boolean,
  48. default: false
  49. },
  50. num: {
  51. type: Number,
  52. default: 1
  53. },
  54. rule: {
  55. type: Object,
  56. default: null
  57. },
  58. videos: {
  59. type: Array,
  60. default: () => [],
  61. require: true
  62. },
  63. },
  64. data() {
  65. return {
  66. uploadingLoading: false,
  67. Storage_key: 'partUploadData',
  68. File_V: null,
  69. tempFilePath: null,
  70. playVideoUrl: '',
  71. }
  72. },
  73. watch: {
  74. uploadingLoading: {
  75. handler(newL, oldL) {
  76. if (newL) {
  77. uni.showLoading({
  78. title: '上传视频中',
  79. mask: true
  80. })
  81. } else {
  82. uni.hideLoading()
  83. }
  84. },
  85. }
  86. },
  87. mounted() {
  88. },
  89. methods: {
  90. popupChange(e) {
  91. if (!e || !e.show) {
  92. this.playVideoUrl = null;
  93. }
  94. },
  95. // 播放视频
  96. onplay(url) {
  97. try {
  98. this.playVideoUrl = url;
  99. this.$refs.videoPlayRef.open();
  100. this.$nextTick(() => {
  101. try {
  102. this.videoContext = uni.createVideoContext('myVideo');
  103. this.videoContext.play();
  104. } catch (e) {
  105. console.log('onpssssslay = ', e)
  106. //TODO handle the exception
  107. }
  108. })
  109. } catch (e) {
  110. console.log('onplay = ', e)
  111. //TODO handle the exception
  112. }
  113. },
  114. delVldeo(index) {
  115. this.videos.splice(index, 1);
  116. },
  117. upLoadError(message = '') {
  118. this.uploadingLoading = false;
  119. uni.showToast({
  120. title: message || '上传失败',
  121. icon: 'none'
  122. })
  123. },
  124. onChooseVideo() {
  125. try {
  126. let that = this;
  127. uni.chooseVideo({
  128. sourceType: ['camera', 'album'],
  129. compressed: false, // 压缩
  130. success: res_file => {
  131. const max_size = 200 * 1024 * 1024;
  132. console.log('max_size', res_file)
  133. if (res_file.size > max_size) {
  134. uni.showToast({
  135. title: '最大上传200M视频',
  136. icon: 'none'
  137. })
  138. return
  139. };
  140. this.onCheckBigFile(res_file.tempFile)
  141. },
  142. fail: err => {
  143. this.upLoadError()
  144. }
  145. });
  146. } catch (e) {
  147. this.upLoadError()
  148. }
  149. },
  150. async onCheckBigFile(file) {
  151. this.uploadingLoading = true
  152. try {
  153. const fileMd5 = await getFileMd5(file)
  154. // 检查是否上传过
  155. getcheckBigFile_Api({
  156. fileMd5: fileMd5,
  157. originalName: file.name
  158. }).then(res => {
  159. const { bigStatus, uploadId, url } = res.data || {};
  160. if (!bigStatus) {
  161. this.saveFileChunk(file, fileMd5, uploadId);
  162. } else {
  163. this.unloadVideos(url);
  164. }
  165. }).catch(err => {
  166. this.upLoadError()
  167. })
  168. } catch (e) {
  169. this.upLoadError()
  170. }
  171. },
  172. // 保存文件片段到后台
  173. saveFileChunk(File, fileMd5, uploadId) {
  174. try {
  175. // 每片的大小为 5M 可调整
  176. const chunkSize = 5 * 1024 * 1024
  177. // 文件分片储存
  178. let chunkList = []
  179. function chunkPush(page = 1) {
  180. chunkList.push(File.slice((page - 1) * chunkSize, page * chunkSize))
  181. // that.uploadFileObj.uploadUrls.push({});
  182. if (page * chunkSize < File.size) {
  183. chunkPush(page + 1)
  184. }
  185. }
  186. chunkPush();
  187. let list = [];
  188. chunkList.forEach((el, i) => {
  189. let p = new Promise((resolve, reject) => {
  190. uni.uploadFile({
  191. url: this.$mConfig.baseUrl + `/common/upload-tag`,
  192. file: File,
  193. formData: {
  194. fileMd5: fileMd5,
  195. uploadId: uploadId,
  196. curPartSize: el.size,
  197. partNumber: i + 1
  198. },
  199. name: 'file',
  200. success: (uploadFileRes) => {
  201. const JSON_data = uploadFileRes.data;
  202. const data = JSON.parse(JSON_data);
  203. const { tag } = data.data
  204. resolve(tag)
  205. },
  206. fail: err => {
  207. this.upLoadError()
  208. }
  209. });
  210. })
  211. list.push(p)
  212. })
  213. Promise.all(list).then(tagsList => {
  214. this.bigFileMergeFun(fileMd5, tagsList, uploadId)
  215. }).catch(() => {
  216. this.upLoadError()
  217. })
  218. } catch (e) {
  219. this.upLoadError()
  220. //TODO handle the exception
  221. }
  222. },
  223. bigFileMergeFun(fileMd5, tagsList, uploadId) {
  224. try {
  225. getMargeTag_Api({ fileMd5: fileMd5, tagsList: tagsList, uploadId: uploadId }).then(res => {
  226. const { url } = res.data || {};
  227. this.unloadVideos(url)
  228. }).catch(err => {
  229. this.upLoadError()
  230. })
  231. } catch (e) {
  232. this.upLoadError()
  233. }
  234. },
  235. unloadVideos(url) {
  236. if (url) {
  237. this.videos.push(url)
  238. this.uploadingLoading = false;
  239. uni.showToast({
  240. title: '上传成功',
  241. icon: 'none'
  242. })
  243. } else {
  244. this.upLoadError()
  245. }
  246. }
  247. }
  248. }
  249. </script>
  250. <style lang="scss" scoped>
  251. @import '~./submint.scss';
  252. </style>