|
|
@@ -0,0 +1,302 @@
|
|
|
+<template>
|
|
|
+ <el-main>
|
|
|
+ <router-view />
|
|
|
+ <el-row v-if="video !== null" class="movie-list">
|
|
|
+ <el-col :md="15">
|
|
|
+ <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="goToVideo">
|
|
|
+ 原视频
|
|
|
+ </el-button>
|
|
|
+ </el-row>
|
|
|
+ <el-row>
|
|
|
+ <h3 v-html="video.title" />
|
|
|
+ </el-row>
|
|
|
+ <el-row style="color: #999;font-size: 16px;padding-top: 0px;">
|
|
|
+ <span><i class="el-icon-video-play">{{ video.view }}</i></span>
|
|
|
+ <span v-html="' '" />
|
|
|
+ <span><i class="el-icon-s-comment">{{ video.comment }}</i></span>
|
|
|
+ <span v-html="' '" />
|
|
|
+ <span><i class="el-icon-watch">{{ video.pubDate }}</i></span>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+ <div class="text item">
|
|
|
+ <div id="dplayer" ref="dplayer" style="height: 480px;" />
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+ </el-row>
|
|
|
+ <el-row style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
|
|
|
+ <el-card class="box-card">
|
|
|
+ <div class="text item">
|
|
|
+ <!--视频描述行-->
|
|
|
+ <span>
|
|
|
+ <p style="white-space:pre-wrap" v-html="video.description" />
|
|
|
+ </span>
|
|
|
+ <el-divider />
|
|
|
+ <!--视频标签行-->
|
|
|
+ <div>
|
|
|
+ <el-tag
|
|
|
+ v-for="(tag,index) in video.tags"
|
|
|
+ :key="index"
|
|
|
+ class="tag"
|
|
|
+ size="medium"
|
|
|
+ effect="plain"
|
|
|
+ >
|
|
|
+ <router-link style="text-decoration-line: none" target="_blank" :to="`/video/tag/` + tag">
|
|
|
+ {{ tag }}
|
|
|
+ </router-link>
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+ </el-row>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-main>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import UserAvatarCard from '@/components/card/UserAvatarCard'
|
|
|
+
|
|
|
+import DPlayer from 'dplayer'
|
|
|
+import { videoInfo, videoUrl } from '@/api/video'
|
|
|
+import { getShortVideo } from '@/api/video'
|
|
|
+import { getUserInfo } from '@/api/user'
|
|
|
+import { getAccessToken } from '@/utils/auth'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'ShortVideo',
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ // 屏幕宽度, 为了控制分页条的大小
|
|
|
+ screenWidth: document.body.clientWidth,
|
|
|
+ shareId: null,
|
|
|
+ video: null,
|
|
|
+ user: null,
|
|
|
+ userToken: null,
|
|
|
+ danmaku: {
|
|
|
+ api: process.env.VUE_APP_SERVER_URL + '/api/comment/danmaku/'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ // 地址栏 url 发生变化时重新加载本页面
|
|
|
+ $route() {
|
|
|
+ this.$router.go()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.userToken = getAccessToken()
|
|
|
+ this.shareId = this.$route.params.shareId
|
|
|
+ this.getVideoInfo(this.shareId)
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ const header = this.$refs.header
|
|
|
+ if (header !== undefined && header !== null) {
|
|
|
+ this.wrapStyle = `height: calc(100vh - ${header.clientHeight + 20}px)`
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 获取视频的详细信息
|
|
|
+ getVideoInfo(videoId) {
|
|
|
+ videoInfo(videoId).then(resp => {
|
|
|
+ if (resp.code === 0) {
|
|
|
+ this.video = resp.data
|
|
|
+ this.getVideoUrl(this.video.videoId)
|
|
|
+ document.title = resp.data.title
|
|
|
+ this.userId = resp.data.userId
|
|
|
+ getUserInfo(this.userId).then(resp => {
|
|
|
+ if (resp.code === 0) {
|
|
|
+ this.user = resp.data
|
|
|
+ } else {
|
|
|
+ this.$notify.error({
|
|
|
+ message: '用户数据获取失败',
|
|
|
+ type: 'warning',
|
|
|
+ duration: 3000
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }).catch(error => {
|
|
|
+ this.$notify.error({
|
|
|
+ message: error.message,
|
|
|
+ type: 'warning',
|
|
|
+ duration: 3000
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ getShortVideoWrapper() {
|
|
|
+ getShortVideo().then(resp => {
|
|
|
+ if (resp.code === 0) {
|
|
|
+ this.video = resp.data
|
|
|
+ document.title = resp.data.title
|
|
|
+ this.getVideoUrl(this.video.videoId)
|
|
|
+ this.userId = resp.data.userId
|
|
|
+ getUserInfo(this.userId).then(resp => {
|
|
|
+ if (resp.code === 0) {
|
|
|
+ this.user = resp.data
|
|
|
+ } else {
|
|
|
+ this.$notify.error({
|
|
|
+ message: '用户数据获取失败',
|
|
|
+ type: 'warning',
|
|
|
+ duration: 3000
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }).catch(error => {
|
|
|
+ this.$notify.error({
|
|
|
+ message: error.message,
|
|
|
+ type: 'warning',
|
|
|
+ duration: 3000
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ 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.error({
|
|
|
+ message: '视频 url 获取失败',
|
|
|
+ type: 'warning',
|
|
|
+ duration: 3000
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }).catch(error => {
|
|
|
+ this.$notify.error({
|
|
|
+ message: error.message,
|
|
|
+ type: 'error',
|
|
|
+ duration: 3000
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ 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
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置音量
|
|
|
+ // player.volume(0.1, true, false)
|
|
|
+ // 跳转到上次看到的位置
|
|
|
+ player.seek(pos)
|
|
|
+
|
|
|
+ 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)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ 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
|
|
|
+
|
|
|
+ const jsonData = {}
|
|
|
+ jsonData.event = 'media_progress'
|
|
|
+ jsonData.data = JSON.stringify(payload)
|
|
|
+
|
|
|
+ that.wsClient.send(jsonData)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ player.on('volumechange', () => {
|
|
|
+ console.log('声音改变')
|
|
|
+ })
|
|
|
+ },
|
|
|
+ goToVideo() {
|
|
|
+ console.log(this.shareId)
|
|
|
+ this.$router.push('/video/' + this.video.videoId)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+/*处于手机屏幕时*/
|
|
|
+@media screen and (max-width: 768px) {
|
|
|
+ .movie-list {
|
|
|
+ padding-top: 8px;
|
|
|
+ padding-left: 0.5%;
|
|
|
+ padding-right: 0.5%;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.movie-list {
|
|
|
+ padding-top: 15px;
|
|
|
+ padding-left: 5%;
|
|
|
+ padding-right: 5%;
|
|
|
+}
|
|
|
+
|
|
|
+.clearfix:before,
|
|
|
+.clearfix:after {
|
|
|
+ display: table;
|
|
|
+ content: "";
|
|
|
+}
|
|
|
+
|
|
|
+.clearfix:after {
|
|
|
+ clear: both;
|
|
|
+}
|
|
|
+
|
|
|
+.logo {
|
|
|
+ width: 30px;
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+</style>
|