|
|
@@ -11,9 +11,24 @@
|
|
|
</v-col>
|
|
|
</v-row>
|
|
|
<v-row justify="center">
|
|
|
- <v-col cols="10">
|
|
|
- <FilePondUpload @video="uploadCallback" />
|
|
|
- </v-col>
|
|
|
+ <div>
|
|
|
+ <uploader
|
|
|
+ class="uploader-example"
|
|
|
+ :options="options"
|
|
|
+ :autoStart="true"
|
|
|
+ @file-added="onFileAdded"
|
|
|
+ @file-success="onFileSuccess"
|
|
|
+ @file-progress="onFileProgress"
|
|
|
+ @file-error="onFileError"
|
|
|
+ >
|
|
|
+ <uploader-unsupport />
|
|
|
+ <uploader-drop>
|
|
|
+ <p>拖动视频文件到此处或</p>
|
|
|
+ <uploader-btn :attrs="attrs">选择视频文件</uploader-btn>
|
|
|
+ </uploader-drop>
|
|
|
+ <uploader-list />
|
|
|
+ </uploader>
|
|
|
+ </div>
|
|
|
</v-row>
|
|
|
<v-row justify="center">
|
|
|
<v-col cols="10">
|
|
|
@@ -23,7 +38,7 @@
|
|
|
<v-row justify="center">
|
|
|
<v-col cols="5">
|
|
|
<v-card outlined>
|
|
|
- <v-img :src="videoInfo.coverUrl" aspect-ratio="1.77" contain max-height="150" alt="封面图,推荐16:9" />
|
|
|
+ <v-img :src="videoPost.coverUrl" aspect-ratio="1.77" contain max-height="150" alt="封面图,推荐16:9" />
|
|
|
</v-card>
|
|
|
</v-col>
|
|
|
<v-col cols="5">
|
|
|
@@ -59,18 +74,18 @@
|
|
|
<v-row justify="center">
|
|
|
<v-col cols="10">
|
|
|
<v-text-field
|
|
|
- v-model="videoInfo.title"
|
|
|
+ v-model="videoPost.title"
|
|
|
placeholder="标题"
|
|
|
label="标题(50字以内)"
|
|
|
clearable
|
|
|
- :rules="[() => videoInfo.title != null || '标题不能为空']"
|
|
|
+ :rules="[() => videoPost.title != null || '标题不能为空']"
|
|
|
/>
|
|
|
</v-col>
|
|
|
</v-row>
|
|
|
<v-row justify="center">
|
|
|
<v-col cols="10">
|
|
|
<v-textarea
|
|
|
- v-model="videoInfo.description"
|
|
|
+ v-model="videoPost.description"
|
|
|
label="简介(200字以内)"
|
|
|
clearable
|
|
|
placeholder="填写更全面的视频信息,让更多的人找到你!"
|
|
|
@@ -80,7 +95,7 @@
|
|
|
<v-row justify="center">
|
|
|
<v-col cols="10">
|
|
|
<v-combobox
|
|
|
- v-model="videoInfo.tags"
|
|
|
+ v-model="videoPost.tags"
|
|
|
label="添加标签让更多人找到你(最多6个)"
|
|
|
multiple
|
|
|
chips
|
|
|
@@ -117,38 +132,49 @@
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import FilePondUpload from '@/components/upload/filepond-upload.vue'
|
|
|
import { videoCategory, submitVideoPost } from '@/api/media/video'
|
|
|
+import { hashFile } from '@/utils/hash'
|
|
|
+
|
|
|
export default {
|
|
|
- components: {
|
|
|
- FilePondUpload
|
|
|
- },
|
|
|
data() {
|
|
|
return {
|
|
|
+ options: {
|
|
|
+ target: '//localhost:8000' + '/api/file/upload/video',
|
|
|
+ chunkSize: 1024 * 1024 * 20,
|
|
|
+ forceChunkSize: true,
|
|
|
+ fileParameterName: 'file',
|
|
|
+ maxChunkRetries: 3,
|
|
|
+ testChunks: true,
|
|
|
+ checkChunkUploadedByResponse: function(chunk, message) {
|
|
|
+ const objMessage = JSON.parse(message)
|
|
|
+ console.log('分片文件检验')
|
|
|
+ console.log(objMessage)
|
|
|
+ if (objMessage.skipUpload) {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+
|
|
|
+ return (objMessage.uploaded || []).indexOf(chunk.offset + 1) >= 0
|
|
|
+ },
|
|
|
+ headers: {
|
|
|
+ Authorization: 'Bearer ' + this.$store.getters.token
|
|
|
+ }
|
|
|
+ },
|
|
|
+ attrs: {
|
|
|
+ accept: 'video/*'
|
|
|
+ },
|
|
|
rules: [
|
|
|
value => !value || value.size < 2000000 || 'Avatar size should be less than 2 MB!'
|
|
|
],
|
|
|
- videoPost: {
|
|
|
- videoUploadId: null,
|
|
|
- videoUrl: null,
|
|
|
- coverUploadId: null,
|
|
|
- coverUrl: null,
|
|
|
- title: '',
|
|
|
- description: '',
|
|
|
- duration: 0,
|
|
|
- categoryId: -1,
|
|
|
- tags: []
|
|
|
- },
|
|
|
// 提交给后端的数据
|
|
|
- videoInfo: {
|
|
|
- videoId: '',
|
|
|
+ videoPost: {
|
|
|
+ fileId: '',
|
|
|
+ videoUrl: '',
|
|
|
coverUrl: '',
|
|
|
title: '',
|
|
|
description: '',
|
|
|
duration: 0,
|
|
|
categoryId: -1,
|
|
|
- tags: [],
|
|
|
- fileId: ''
|
|
|
+ tags: []
|
|
|
},
|
|
|
categoryMap: {
|
|
|
Set: function(key, value) { this[key] = value },
|
|
|
@@ -168,25 +194,75 @@ export default {
|
|
|
this.getVideoCategory()
|
|
|
},
|
|
|
methods: {
|
|
|
+ onFileAdded(file) {
|
|
|
+ file.pause()
|
|
|
+ hashFile(file.file).then(res => {
|
|
|
+ this.setTitle(file.file.name)
|
|
|
+ const formData = new FormData()
|
|
|
+ formData.append('filename', file.file.name)
|
|
|
+ formData.append('size', file.file.size)
|
|
|
+ formData.append('sha256sum', res.sha256sum)
|
|
|
+ fetch(`//localhost:8000` + `/api/file/upload/video/prepare`, {
|
|
|
+ headers: {
|
|
|
+ Authorization: 'Bearer ' + this.$store.getters.token
|
|
|
+ },
|
|
|
+ method: 'POST',
|
|
|
+ credentials: 'include',
|
|
|
+ body: formData
|
|
|
+ }).then(response => response.json())
|
|
|
+ .then(json => {
|
|
|
+ const uploadId = json.data.uploadId
|
|
|
+ const exist = json.data.exist
|
|
|
+ if (exist) {
|
|
|
+ this.message = '视频已存在'
|
|
|
+ this.showMessage = true
|
|
|
+ file.cancel()
|
|
|
+ } else {
|
|
|
+ this.videoPost.videoId = uploadId
|
|
|
+ file.uniqueIdentifier = uploadId
|
|
|
+ file.resume()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(e => {
|
|
|
+ return null
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ onFileProgress(rootFile, file, chunk) {
|
|
|
+ },
|
|
|
+ onFileSuccess(rootFile, file, response, chunk) {
|
|
|
+ const res = JSON.parse(response)
|
|
|
+ if (res.code === 0) {
|
|
|
+ const resData = res.data
|
|
|
+ if (resData.merged) {
|
|
|
+ this.videoPost.fileId = resData.uploadId
|
|
|
+ this.videoPost.videoUrl = resData.videoUrl
|
|
|
+ this.videoPost.coverUrl = resData.coverUrl
|
|
|
+ this.videoPost.duration = resData.duration
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onFileError(rootFile, file, response, chunk) {
|
|
|
+ console.log('文件上传错误')
|
|
|
+ },
|
|
|
publish() {
|
|
|
- if (!this.videoInfo.fileId) {
|
|
|
+ if (!this.videoPost.fileId) {
|
|
|
this.message = '你还没有上传视频'
|
|
|
this.showMessage = true
|
|
|
return
|
|
|
}
|
|
|
- if (this.videoInfo.title === '' || this.coverUrl === '' || this.videoInfo.tags.length === 0 || this.videoInfo.categoryId === -1) {
|
|
|
+ if (this.videoPost.title === '' || this.videoPost.coverUrl === '' || this.videoPost.tags.length === 0 || this.videoPost.categoryId === -1) {
|
|
|
this.message = '标题,封面,标签,分区不能为空'
|
|
|
this.showMessage = true
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
- if (this.videoInfo.tags.length > 6) {
|
|
|
+ if (this.videoPost.tags.length > 6) {
|
|
|
this.message = '标签超过6个'
|
|
|
this.showMessage = true
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- submitVideoPost(this.videoInfo)
|
|
|
+ submitVideoPost(this.videoPost)
|
|
|
.then(res => {
|
|
|
if (res.code === 0) {
|
|
|
this.message = '投稿成功,等待审核通过后你就可以看到你的视频了'
|
|
|
@@ -205,32 +281,11 @@ export default {
|
|
|
this.files = []
|
|
|
this.files.push(value)
|
|
|
},
|
|
|
- // filepond 组件上传文件完成时调用
|
|
|
- uploadCallback(value) {
|
|
|
- console.log(value)
|
|
|
- /* if (value.code === 0) {
|
|
|
- this.videoInfo.videoId = value.data.videoId
|
|
|
- this.setTitle(value.data.filename)
|
|
|
- this.videoInfo.duration = value.data.duration
|
|
|
- this.videoInfo.coverUrl = value.data.coverUrl
|
|
|
- this.videoInfo.fileId = value.data.fileId
|
|
|
-
|
|
|
- this.message = '视频上传成功'
|
|
|
- this.showMessage = true
|
|
|
- } else {
|
|
|
- if (value.msg != null) {
|
|
|
- this.message = '上传文件出现异常,请重新上传!' + value.msg
|
|
|
- } else {
|
|
|
- this.message = '上传文件出现异常,请重新上传!'
|
|
|
- }
|
|
|
- this.showMessage = true
|
|
|
- }*/
|
|
|
- },
|
|
|
setTitle(title) {
|
|
|
if (title.length > 50) {
|
|
|
- this.videoInfo.title = title.substring(0, 50)
|
|
|
+ this.videoPost.title = title.substring(0, 50)
|
|
|
} else {
|
|
|
- this.videoInfo.title = title
|
|
|
+ this.videoPost.title = title
|
|
|
}
|
|
|
},
|
|
|
uploadFile() {
|
|
|
@@ -245,7 +300,7 @@ export default {
|
|
|
}
|
|
|
fetch(`http://file.reghao.cn/api/file/upload/image`, {
|
|
|
headers: {
|
|
|
- 'X-XSRF-TOKEN': this.$cookies.get('XSRF-TOKEN')
|
|
|
+ 'Authorization': 'Bearer ' + this.$store.getters.token
|
|
|
},
|
|
|
method: 'POST',
|
|
|
credentials: 'include',
|
|
|
@@ -253,7 +308,7 @@ export default {
|
|
|
}).then(response => response.json())
|
|
|
.then(json => {
|
|
|
if (json.code === 0) {
|
|
|
- this.videoInfo.coverUrl = json.data[0].url
|
|
|
+ this.videoPost.coverUrl = json.data[0].url
|
|
|
} else {
|
|
|
this.message = '上传失败,请重试!' + json.message
|
|
|
this.showMessage = true
|
|
|
@@ -284,7 +339,7 @@ export default {
|
|
|
// 重置子分区,清除前一次选择分区时留下的缓存
|
|
|
this.childCategory = []
|
|
|
this.currentCategory = this.categoryMap.Get(name)
|
|
|
- this.videoInfo.categoryId = this.currentCategory.id
|
|
|
+ this.videoPost.categoryId = this.currentCategory.id
|
|
|
|
|
|
const c = this.currentCategory.children
|
|
|
if (c) {
|
|
|
@@ -297,7 +352,7 @@ export default {
|
|
|
const c = this.currentCategory.children
|
|
|
for (let i = 0; i < c.length; i++) {
|
|
|
if (c[i].name === name) {
|
|
|
- this.videoInfo.categoryId = c[i].id
|
|
|
+ this.videoPost.categoryId = c[i].id
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -306,4 +361,20 @@ export default {
|
|
|
</script>
|
|
|
|
|
|
<style>
|
|
|
+ .uploader-example {
|
|
|
+ width: 500px;
|
|
|
+ padding: 15px;
|
|
|
+ margin: 40px auto 0;
|
|
|
+ font-size: 12px;
|
|
|
+ box-shadow: 0 0 10px rgba(0, 0, 0, .4);
|
|
|
+ }
|
|
|
+ .uploader-example .uploader-btn {
|
|
|
+ margin-right: 4px;
|
|
|
+ }
|
|
|
+ .uploader-example .uploader-list {
|
|
|
+ max-height: 440px;
|
|
|
+ overflow: auto;
|
|
|
+ overflow-x: hidden;
|
|
|
+ overflow-y: auto;
|
|
|
+ }
|
|
|
</style>
|