|
|
@@ -4,6 +4,9 @@
|
|
|
<el-row style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
|
|
|
<el-card class="box-card">
|
|
|
<div slot="header" class="clearfix">
|
|
|
+ <el-row>
|
|
|
+ <el-button style="float: right; padding: 3px 0" type="text" @click="nextVideo">下一个</el-button>
|
|
|
+ </el-row>
|
|
|
<el-row>
|
|
|
<h3 v-html="video.title" />
|
|
|
</el-row>
|
|
|
@@ -13,10 +16,6 @@
|
|
|
<span><i class="el-icon-s-comment">{{ video.comment }}</i></span>
|
|
|
<span v-html="' '" />
|
|
|
<span><i class="el-icon-watch">{{ video.pubDate }}</i></span>
|
|
|
- <span v-html="' '" />
|
|
|
- <span v-if="videoId !== null && videoId.includes('BV')"><i class="el-icon-apple">
|
|
|
- <a target="_blank" :href="`https://bilibili.com/` + videoId">bili</a>
|
|
|
- </i></span>
|
|
|
</el-row>
|
|
|
</div>
|
|
|
<div class="text item">
|
|
|
@@ -24,161 +23,10 @@
|
|
|
</div>
|
|
|
</el-card>
|
|
|
</el-row>
|
|
|
- <el-row style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
|
|
|
- <el-card class="box-card">
|
|
|
- <div slot="header" class="clearfix">
|
|
|
- <div class="video-data-row">
|
|
|
- <el-button
|
|
|
- type="danger"
|
|
|
- size="mini"
|
|
|
- icon="el-icon-plus"
|
|
|
- :disabled="isCollected"
|
|
|
- @click="collection(video.videoId)"
|
|
|
- >
|
|
|
- <span>收藏 {{ video.favorite }}</span>
|
|
|
- </el-button>
|
|
|
- <el-button
|
|
|
- type="danger"
|
|
|
- size="mini"
|
|
|
- icon="el-icon-thumb"
|
|
|
- :disabled="isCollected"
|
|
|
- @click="collection(video.videoId)"
|
|
|
- >
|
|
|
- <span>喜欢 {{ video.thumbUp }}</span>
|
|
|
- </el-button>
|
|
|
- <el-button
|
|
|
- type="danger"
|
|
|
- size="mini"
|
|
|
- icon="el-icon-share"
|
|
|
- :disabled="isCollected"
|
|
|
- @click="getShareUrl(video.videoId)"
|
|
|
- >
|
|
|
- <span>分享 {{ video.share }}</span>
|
|
|
- </el-button>
|
|
|
- <el-button
|
|
|
- type="danger"
|
|
|
- size="mini"
|
|
|
- icon="el-icon-download"
|
|
|
- @click="getDownloadUrl(video.videoId)"
|
|
|
- >
|
|
|
- <span>下载</span>
|
|
|
- </el-button>
|
|
|
- <el-button
|
|
|
- type="danger"
|
|
|
- size="mini"
|
|
|
- icon="el-icon-help"
|
|
|
- @click="displayErrorReportDialog"
|
|
|
- >
|
|
|
- <span>报错</span>
|
|
|
- </el-button>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="text item">
|
|
|
- <!--视频描述行-->
|
|
|
- <span class="description" v-html="video.description" />
|
|
|
- <el-divider />
|
|
|
- <!--视频标签行-->
|
|
|
- <div class="v-tag">
|
|
|
- <el-tag
|
|
|
- v-for="(tag,index) in video.tags"
|
|
|
- :key="index"
|
|
|
- class="tag"
|
|
|
- size="medium"
|
|
|
- effect="plain"
|
|
|
- >
|
|
|
- <router-link target="_blank" :to="`/video/tag/` + tag">
|
|
|
- {{ tag }}
|
|
|
- </router-link>
|
|
|
- </el-tag>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </el-card>
|
|
|
- </el-row>
|
|
|
<el-row style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
|
|
|
<user-avatar-card v-if="user !== null" :user-avatar="user" />
|
|
|
</el-row>
|
|
|
- <el-row style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
|
|
|
- <el-card class="box-card">
|
|
|
- <div slot="header" class="clearfix">
|
|
|
- <el-row>
|
|
|
- <h3>视频评论</h3>
|
|
|
- </el-row>
|
|
|
- </div>
|
|
|
- <div class="text item">
|
|
|
- <div ref="comment" :style="wrapStyle" class="comment-wrap">
|
|
|
- <comment
|
|
|
- v-model="dataList"
|
|
|
- :user="currentUser"
|
|
|
- :props="props"
|
|
|
- :before-submit="submit"
|
|
|
- :before-like="like"
|
|
|
- :before-delete="deleteComment"
|
|
|
- :upload-img="uploadImg"
|
|
|
- />
|
|
|
- <el-pagination
|
|
|
- :small="screenWidth <= 768"
|
|
|
- hide-on-single-page
|
|
|
- layout="prev, pager, next"
|
|
|
- :page-size="pageSize"
|
|
|
- :current-page="currentPage"
|
|
|
- :total="totalSize"
|
|
|
- @current-change="handleCurrentChange"
|
|
|
- />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </el-card>
|
|
|
- </el-row>
|
|
|
</el-col>
|
|
|
-
|
|
|
- <!-- 添加到播放列表对话框 -->
|
|
|
- <el-dialog
|
|
|
- append-to-body
|
|
|
- :visible.sync="showPlaylistDialog"
|
|
|
- width="30%"
|
|
|
- center
|
|
|
- >
|
|
|
- <el-card class="box-card">
|
|
|
- <div slot="header" class="clearfix">
|
|
|
- <el-button style="float: right; padding: 3px 0" type="text" @click="createAlbum">
|
|
|
- 创建播放列表
|
|
|
- </el-button>
|
|
|
- <el-form v-if="showCreateAlbum" ref="form" :model="albumForm" label-width="80px">
|
|
|
- <el-form-item>
|
|
|
- <el-input v-model="albumForm.albumName" style="padding-right: 1px" placeholder="标题不能超过 50 个字符" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item>
|
|
|
- <el-button type="plain" @click="onCreateAlbum">确定</el-button>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- </div>
|
|
|
- <div class="text item">
|
|
|
- <el-table
|
|
|
- :data="playlist"
|
|
|
- border
|
|
|
- style="width: 100%"
|
|
|
- >
|
|
|
- <el-table-column
|
|
|
- prop="albumName"
|
|
|
- label="播放列表"
|
|
|
- />
|
|
|
- <el-table-column
|
|
|
- prop="total"
|
|
|
- label="数量"
|
|
|
- />
|
|
|
- <el-table-column label="收藏" width="80" align="center">
|
|
|
- <template slot-scope="scope">
|
|
|
- <el-button
|
|
|
- type="danger"
|
|
|
- size="mini"
|
|
|
- icon="el-icon-plus"
|
|
|
- @click="addToPlaylist(scope.row)"
|
|
|
- />
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- </el-table>
|
|
|
- </div>
|
|
|
- </el-card>
|
|
|
- </el-dialog>
|
|
|
</el-row>
|
|
|
</template>
|
|
|
|
|
|
@@ -193,55 +41,11 @@ import { getAccessToken } from '@/utils/auth'
|
|
|
|
|
|
export default {
|
|
|
name: 'ShortVideo',
|
|
|
- components: { VideoPlayer, UserAvatarCard, comment },
|
|
|
+ components: { UserAvatarCard },
|
|
|
data() {
|
|
|
return {
|
|
|
// 屏幕宽度, 为了控制分页条的大小
|
|
|
screenWidth: document.body.clientWidth,
|
|
|
- currentPage: 1,
|
|
|
- pageSize: 20,
|
|
|
- totalSize: 0,
|
|
|
- dataList: [],
|
|
|
- // ********************************************************************/
|
|
|
- wrapStyle: '',
|
|
|
- videoComments: [
|
|
|
- {
|
|
|
- commentId: 114511,
|
|
|
- content: 'this is comment content',
|
|
|
- imageUrl: '',
|
|
|
- children: [],
|
|
|
- likes: 0,
|
|
|
- liked: false,
|
|
|
- reply: null,
|
|
|
- createAt: 1700271326393,
|
|
|
- user: {
|
|
|
- userId: 1,
|
|
|
- name: '西瓜',
|
|
|
- avatar: ''
|
|
|
- }
|
|
|
- }
|
|
|
- ],
|
|
|
- currentUser: {
|
|
|
- userId: 9999,
|
|
|
- name: '芒果',
|
|
|
- avatar: '//picx.zhimg.com/v2-a2c89378a6332cbfed3e28b5ab84feb7.jpg',
|
|
|
- author: true
|
|
|
- },
|
|
|
- // 自定义组件中 comment 对象的字段名
|
|
|
- props: {
|
|
|
- id: 'commentId',
|
|
|
- content: 'content',
|
|
|
- imgSrc: 'imageUrl',
|
|
|
- children: 'children',
|
|
|
- likes: 'likes',
|
|
|
- liked: 'liked',
|
|
|
- reply: 'reply',
|
|
|
- createAt: 'createAt',
|
|
|
- total: 'total',
|
|
|
- user: 'user'
|
|
|
- },
|
|
|
- // ********************************************************************/
|
|
|
- videoId: null,
|
|
|
video: null,
|
|
|
user: null,
|
|
|
userToken: null,
|
|
|
@@ -261,39 +65,7 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
- // ****************************************************************************************************************
|
|
|
- handleCurrentChange(currentPage) {
|
|
|
- this.currentPage = currentPage
|
|
|
- this.getCommentWrapper(currentPage)
|
|
|
- // 回到顶部
|
|
|
- scrollTo(0, 0)
|
|
|
- },
|
|
|
- getCommentWrapper(pageNumber) {
|
|
|
- getComment(this.videoId, pageNumber).then(resp => {
|
|
|
- if (resp.code === 0) {
|
|
|
- const respData = resp.data
|
|
|
- this.dataList = respData.list
|
|
|
- this.totalSize = respData.totalSize
|
|
|
- } else {
|
|
|
- this.$notify({
|
|
|
- title: '提示',
|
|
|
- message: resp.msg,
|
|
|
- type: 'error',
|
|
|
- duration: 3000
|
|
|
- })
|
|
|
- }
|
|
|
- }).catch(error => {
|
|
|
- this.$notify({
|
|
|
- title: '提示',
|
|
|
- message: error.message,
|
|
|
- type: 'warning',
|
|
|
- duration: 3000
|
|
|
- })
|
|
|
- })
|
|
|
- },
|
|
|
- // ****************************************************************************************************************
|
|
|
- // 获取视频的详细信息
|
|
|
- getVideoInfo() {
|
|
|
+ getShortVideoWrapper() {
|
|
|
getShortVideo().then(resp => {
|
|
|
if (resp.code === 0) {
|
|
|
this.video = resp.data
|
|
|
@@ -320,235 +92,116 @@ export default {
|
|
|
})
|
|
|
})
|
|
|
},
|
|
|
- // 获取和当前视频类似的其他视频
|
|
|
- getSimilarVideos(videoId) {
|
|
|
- similarVideo(videoId).then(resp => {
|
|
|
- if (resp.code === 0) {
|
|
|
- this.similarVideos = resp.data
|
|
|
- } else {
|
|
|
- this.$notify.error({
|
|
|
- message: '推荐视频数据获取失败',
|
|
|
- type: 'warning',
|
|
|
- duration: 3000
|
|
|
- })
|
|
|
- }
|
|
|
- }).catch(error => {
|
|
|
- this.$notify.error({
|
|
|
- message: error.message,
|
|
|
- type: 'warning',
|
|
|
- duration: 3000
|
|
|
- })
|
|
|
- })
|
|
|
- },
|
|
|
- // 换一换
|
|
|
- refreshSimilar() {
|
|
|
- console.log('刷新相关推荐')
|
|
|
- },
|
|
|
- // 用户点击收藏
|
|
|
- collection(videoId) {
|
|
|
- this.showPlaylistDialog = true
|
|
|
- const queryInfo = {
|
|
|
- pn: 1,
|
|
|
- userId: this.currentUser.userId
|
|
|
- }
|
|
|
- getUserPlaylist(queryInfo).then(resp => {
|
|
|
- if (resp.code === 0) {
|
|
|
- this.playlist = resp.data.list
|
|
|
- }
|
|
|
- })
|
|
|
- },
|
|
|
- addToPlaylist(row) {
|
|
|
- this.showPlaylistDialog = false
|
|
|
- const jsonData = {}
|
|
|
- jsonData.albumId = row.albumId
|
|
|
- jsonData.postId = this.videoId
|
|
|
- jsonData.action = 1
|
|
|
- collectItem(jsonData).then(resp => {
|
|
|
- if (resp.code === 0) {
|
|
|
- this.$notify.success({
|
|
|
- title: '视频已收藏',
|
|
|
- type: 'success',
|
|
|
- duration: 3000
|
|
|
- })
|
|
|
- } else {
|
|
|
- this.$notify.warning({
|
|
|
- title: '视频收藏失败',
|
|
|
- type: 'warning',
|
|
|
- duration: 3000
|
|
|
- })
|
|
|
- }
|
|
|
- })
|
|
|
- },
|
|
|
- getShareUrl(videoId) {
|
|
|
- getShortUrl(videoId).then(resp => {
|
|
|
- if (resp.code === 0) {
|
|
|
- console.log(resp.data)
|
|
|
- this.video.share += 1
|
|
|
- }
|
|
|
- })
|
|
|
- },
|
|
|
- getDownloadUrl(videoId) {
|
|
|
- // let filename
|
|
|
- downloadVideo(videoId).then(resp => {
|
|
|
- if (resp.code === 0) {
|
|
|
- const downloadUrl = resp.data.url
|
|
|
- window.open(downloadUrl, '_blank')
|
|
|
- /* fetch(downloadUrl.url, {
|
|
|
- headers: {
|
|
|
- Authorization: 'Bearer ' + downloadUrl.token
|
|
|
- },
|
|
|
- method: 'GET',
|
|
|
- credentials: 'include'
|
|
|
- }).then(resp => {
|
|
|
- /!*
|
|
|
- 遍历 formdata
|
|
|
- for (const key of resp.headers.keys()) {
|
|
|
- console.log(key + ' : ' + resp.headers.get(key))
|
|
|
- }*!/
|
|
|
- const header = resp.headers.get('Content-Disposition')
|
|
|
- const parts = header.split(';')
|
|
|
- const encodeFilename = parts[1].split('=')[1]
|
|
|
- filename = decodeURI(encodeFilename)
|
|
|
- return resp.blob()
|
|
|
- }).then(data => {
|
|
|
- const blobUrl = window.URL.createObjectURL(data)
|
|
|
- const a = document.createElement('a')
|
|
|
- a.download = filename
|
|
|
- a.href = blobUrl
|
|
|
- a.click()
|
|
|
- }).catch(e => {
|
|
|
- this.$notify({
|
|
|
- title: '提示',
|
|
|
- message: '视频下载失败',
|
|
|
+ async getVideoUrl(videoId) {
|
|
|
+ videoUrl(videoId).then(res => {
|
|
|
+ if (res.code === 0) {
|
|
|
+ var sendEvent = false
|
|
|
+ const urlType = res.data.type
|
|
|
+ if (urlType === 'mp4') {
|
|
|
+ const urls = res.data.urls
|
|
|
+ for (const url of urls) {
|
|
|
+ url.type = 'normal'
|
|
|
+ }
|
|
|
+ this.initMp4Player(this.userId, videoId, this.video.coverUrl, urls, res.data.currentTime, sendEvent)
|
|
|
+ } else {
|
|
|
+ this.$notify.error({
|
|
|
+ message: '视频 url 类型不合法',
|
|
|
type: 'warning',
|
|
|
duration: 3000
|
|
|
})
|
|
|
- })*/
|
|
|
+ }
|
|
|
} else {
|
|
|
- this.$notify({
|
|
|
- title: '提示',
|
|
|
- message: resp.msg,
|
|
|
+ this.$notify.error({
|
|
|
+ message: '视频 url 获取失败',
|
|
|
type: 'warning',
|
|
|
duration: 3000
|
|
|
})
|
|
|
}
|
|
|
}).catch(error => {
|
|
|
- this.$notify({
|
|
|
- title: '提示',
|
|
|
+ this.$notify.error({
|
|
|
message: error.message,
|
|
|
type: 'error',
|
|
|
duration: 3000
|
|
|
})
|
|
|
})
|
|
|
},
|
|
|
- createAlbum() {
|
|
|
- this.showCreateAlbum = true
|
|
|
- },
|
|
|
- onCreateAlbum() {
|
|
|
- this.showCreateAlbum = false
|
|
|
- createAlbum(this.albumForm).then(resp => {
|
|
|
- if (resp.code === 0) {
|
|
|
- this.playlist.push(resp.data)
|
|
|
+ initMp4Player(userId, videoId, coverUrl, urls, pos, sendEvent) {
|
|
|
+ const player = new DPlayer({
|
|
|
+ container: document.querySelector('#dplayer'),
|
|
|
+ lang: 'zh-cn',
|
|
|
+ screenshot: true,
|
|
|
+ autoplay: false,
|
|
|
+ volume: 0.1,
|
|
|
+ mutex: true,
|
|
|
+ video: {
|
|
|
+ pic: coverUrl,
|
|
|
+ defaultQuality: 0,
|
|
|
+ quality: urls,
|
|
|
+ hotkey: true
|
|
|
+ },
|
|
|
+ danmaku: {
|
|
|
+ id: videoId,
|
|
|
+ maximum: 10000,
|
|
|
+ api: this.danmaku.api,
|
|
|
+ token: this.userToken,
|
|
|
+ bottom: '15%',
|
|
|
+ unlimited: true
|
|
|
}
|
|
|
})
|
|
|
- this.albumForm.albumName = null
|
|
|
- },
|
|
|
- displayErrorReportDialog() {
|
|
|
- this.errorReportForm.videoId = this.video.videoId
|
|
|
- this.showErrorReportDialog = true
|
|
|
- },
|
|
|
- submitErrorReport() {
|
|
|
- this.showErrorReportDialog = false
|
|
|
- videoErrorReport(this.errorReportForm).then(resp => {
|
|
|
- if (resp.code === 0) {
|
|
|
- this.errorReportForm.errorCode = null
|
|
|
- this.$notify({
|
|
|
- title: '提示',
|
|
|
- message: '视频错误已提交',
|
|
|
- type: 'warning',
|
|
|
- duration: 3000
|
|
|
- })
|
|
|
- } else {
|
|
|
- this.$notify({
|
|
|
- title: '提示',
|
|
|
- message: resp.msg,
|
|
|
- type: 'warning',
|
|
|
- duration: 3000
|
|
|
- })
|
|
|
- }
|
|
|
- }).catch(error => {
|
|
|
- this.$notify({
|
|
|
- title: '提示',
|
|
|
- message: error.message,
|
|
|
- type: 'warning',
|
|
|
- duration: 3000
|
|
|
- })
|
|
|
- })
|
|
|
- },
|
|
|
- // ****************************************************************************************************************
|
|
|
- // 评论
|
|
|
- async submit(newComment, parent, add) {
|
|
|
- const res = await new Promise((resolve) => {
|
|
|
- setTimeout(() => {
|
|
|
- resolve({ newComment, parent })
|
|
|
- }, 300)
|
|
|
- })
|
|
|
|
|
|
- add(Object.assign(res.newComment, { postId: this.video.videoId }))
|
|
|
- if (res.parent !== null) {
|
|
|
- // console.log('parent: ', res.parent)
|
|
|
- } else {
|
|
|
- this.totalSize += 1
|
|
|
- }
|
|
|
+ // 设置音量
|
|
|
+ // player.volume(0.1, true, false)
|
|
|
+ // 跳转到上次看到的位置
|
|
|
+ player.seek(pos)
|
|
|
|
|
|
- // console.log('addComment: ', res)
|
|
|
- publishComment(res).then(resp => {
|
|
|
- if (resp.code === 0) {
|
|
|
- this.$notify.success({
|
|
|
- message: '评论已发布',
|
|
|
- duration: 3000
|
|
|
- })
|
|
|
- } else {
|
|
|
- this.$notify.warning({
|
|
|
- message: '评论发布失败',
|
|
|
- duration: 3000
|
|
|
- })
|
|
|
+ var ended = false
|
|
|
+ /* 事件绑定 */
|
|
|
+ const that = this
|
|
|
+ player.on('play', function() {
|
|
|
+ if (sendEvent) {
|
|
|
+ clearInterval(that.intervalEvent)
|
|
|
+ that.intervalEvent = setInterval(() => {
|
|
|
+ if (!ended) {
|
|
|
+ const payload = {}
|
|
|
+ payload.mediaId = videoId
|
|
|
+ payload.mediaType = 1
|
|
|
+ payload.currentTime = player.video.currentTime
|
|
|
+ payload.ended = ended
|
|
|
+
|
|
|
+ const jsonData = {}
|
|
|
+ jsonData.event = 'media_progress'
|
|
|
+ jsonData.data = JSON.stringify(payload)
|
|
|
+
|
|
|
+ that.wsClient.send(jsonData)
|
|
|
+ }
|
|
|
+ }, 5000)
|
|
|
}
|
|
|
})
|
|
|
- },
|
|
|
- async like(comment) {
|
|
|
- const res = await new Promise((resolve) => {
|
|
|
- setTimeout(() => {
|
|
|
- resolve(comment)
|
|
|
- }, 0)
|
|
|
- })
|
|
|
+ player.on('ended', () => {
|
|
|
+ clearInterval(that.intervalEvent)
|
|
|
+ ended = true
|
|
|
+ if (sendEvent) {
|
|
|
+ const payload = {}
|
|
|
+ payload.mediaId = videoId
|
|
|
+ payload.mediaType = 1
|
|
|
+ payload.currentTime = player.video.currentTime
|
|
|
+ payload.ended = ended
|
|
|
|
|
|
- console.log('likeComment: ', res)
|
|
|
- },
|
|
|
- async uploadImg({ file, callback }) {
|
|
|
- const res = await new Promise((resolve, reject) => {
|
|
|
- const reader = new FileReader()
|
|
|
- reader.readAsDataURL(file)
|
|
|
- reader.onload = () => {
|
|
|
- resolve(reader.result)
|
|
|
- }
|
|
|
+ const jsonData = {}
|
|
|
+ jsonData.event = 'media_progress'
|
|
|
+ jsonData.data = JSON.stringify(payload)
|
|
|
|
|
|
- reader.onerror = () => {
|
|
|
- reject(reader.error)
|
|
|
+ that.wsClient.send(jsonData)
|
|
|
}
|
|
|
})
|
|
|
- callback(res)
|
|
|
- console.log('uploadImg: ', res)
|
|
|
- },
|
|
|
- async deleteComment(comment, parent) {
|
|
|
- const res = await new Promise((resolve) => {
|
|
|
- setTimeout(() => {
|
|
|
- resolve({ comment, parent })
|
|
|
- }, 300)
|
|
|
+
|
|
|
+ player.on('volumechange', () => {
|
|
|
+ console.log('声音改变')
|
|
|
})
|
|
|
- console.log('deleteComment: ', res)
|
|
|
+ },
|
|
|
+ async nextVideo() {
|
|
|
+ this.getShortVideoWrapper()
|
|
|
}
|
|
|
- // ****************************************************************************************************************
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
@@ -578,11 +231,4 @@ export default {
|
|
|
.clearfix:after {
|
|
|
clear: both;
|
|
|
}
|
|
|
-
|
|
|
-.v-tag {
|
|
|
- padding-top: 10px;
|
|
|
-}
|
|
|
-.tag{
|
|
|
- margin-right: 3px;
|
|
|
-}
|
|
|
</style>
|