Преглед на файлове

分离视频贴数据和视频地址,使用两个 API 分别获取,处理异步加载播放器组件的问题

reghao преди 4 години
родител
ревизия
a22f072dec

+ 82 - 80
package-lock.json

@@ -1,5 +1,5 @@
 {
-  "name": "itube",
+  "name": "hertube",
   "version": "1.0.0",
   "lockfileVersion": 1,
   "requires": true,
@@ -1734,16 +1734,6 @@
           "integrity": "sha1-4a1IbmxUUBY0xsOXxcEh2qODYHw=",
           "dev": true
         },
-        "ansi-styles": {
-          "version": "4.3.0",
-          "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-4.3.0.tgz?cache=0&sync_timestamp=1618995588464&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fansi-styles%2Fdownload%2Fansi-styles-4.3.0.tgz",
-          "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-convert": "^2.0.1"
-          }
-        },
         "cacache": {
           "version": "13.0.1",
           "resolved": "https://registry.npm.taobao.org/cacache/download/cacache-13.0.1.tgz?cache=0&sync_timestamp=1594427999421&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcacache%2Fdownload%2Fcacache-13.0.1.tgz",
@@ -1770,34 +1760,6 @@
             "unique-filename": "^1.1.1"
           }
         },
-        "chalk": {
-          "version": "4.1.2",
-          "resolved": "https://registry.nlark.com/chalk/download/chalk-4.1.2.tgz?cache=0&sync_timestamp=1627646614989&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchalk%2Fdownload%2Fchalk-4.1.2.tgz",
-          "integrity": "sha1-qsTit3NKdAhnrrFr8CqtVWoeegE=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ansi-styles": "^4.1.0",
-            "supports-color": "^7.1.0"
-          }
-        },
-        "color-convert": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz",
-          "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-name": "~1.1.4"
-          }
-        },
-        "color-name": {
-          "version": "1.1.4",
-          "resolved": "http://registry.npm.taobao.org/color-name/download/color-name-1.1.4.tgz",
-          "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=",
-          "dev": true,
-          "optional": true
-        },
         "find-cache-dir": {
           "version": "3.3.1",
           "resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-3.3.1.tgz?cache=0&sync_timestamp=1583734806517&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffind-cache-dir%2Fdownload%2Ffind-cache-dir-3.3.1.tgz",
@@ -1819,25 +1781,6 @@
             "path-exists": "^4.0.0"
           }
         },
-        "has-flag": {
-          "version": "4.0.0",
-          "resolved": "https://registry.nlark.com/has-flag/download/has-flag-4.0.0.tgz?cache=0&sync_timestamp=1626716578584&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fhas-flag%2Fdownload%2Fhas-flag-4.0.0.tgz",
-          "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=",
-          "dev": true,
-          "optional": true
-        },
-        "loader-utils": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-2.0.0.tgz",
-          "integrity": "sha1-5MrOW4FtQloWa18JfhDNErNgZLA=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "big.js": "^5.2.2",
-            "emojis-list": "^3.0.0",
-            "json5": "^2.1.2"
-          }
-        },
         "locate-path": {
           "version": "5.0.0",
           "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-5.0.0.tgz?cache=0&sync_timestamp=1597082033698&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flocate-path%2Fdownload%2Flocate-path-5.0.0.tgz",
@@ -1902,16 +1845,6 @@
             "minipass": "^3.1.1"
           }
         },
-        "supports-color": {
-          "version": "7.2.0",
-          "resolved": "https://registry.nlark.com/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1626703455199&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz",
-          "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "has-flag": "^4.0.0"
-          }
-        },
         "terser-webpack-plugin": {
           "version": "2.3.8",
           "resolved": "https://registry.npm.taobao.org/terser-webpack-plugin/download/terser-webpack-plugin-2.3.8.tgz",
@@ -1928,18 +1861,6 @@
             "terser": "^4.6.12",
             "webpack-sources": "^1.4.3"
           }
-        },
-        "vue-loader-v16": {
-          "version": "npm:vue-loader@16.5.0",
-          "resolved": "https://registry.nlark.com/vue-loader/download/vue-loader-16.5.0.tgz?cache=0&sync_timestamp=1628666788607&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fvue-loader%2Fdownload%2Fvue-loader-16.5.0.tgz",
-          "integrity": "sha1-CcTgcSRmiZ40uZpoZSTxkWX7KJI=",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "chalk": "^4.1.0",
-            "hash-sum": "^2.0.0",
-            "loader-utils": "^2.0.0"
-          }
         }
       }
     },
@@ -11333,6 +11254,87 @@
         }
       }
     },
+    "vue-loader-v16": {
+      "version": "npm:vue-loader@16.8.3",
+      "resolved": "https://registry.npmmirror.com/vue-loader/download/vue-loader-16.8.3.tgz",
+      "integrity": "sha1-1D5nXe9bqTRdbH8FkUwT2GGZcIc=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "chalk": "^4.1.0",
+        "hash-sum": "^2.0.0",
+        "loader-utils": "^2.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.3.0",
+          "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-4.3.0.tgz?cache=0&sync_timestamp=1618995588464&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fansi-styles%2Fdownload%2Fansi-styles-4.3.0.tgz",
+          "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.1.2",
+          "resolved": "https://registry.npmmirror.com/chalk/download/chalk-4.1.2.tgz",
+          "integrity": "sha1-qsTit3NKdAhnrrFr8CqtVWoeegE=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz",
+          "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "http://registry.npm.taobao.org/color-name/download/color-name-1.1.4.tgz",
+          "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=",
+          "dev": true,
+          "optional": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.nlark.com/has-flag/download/has-flag-4.0.0.tgz?cache=0&sync_timestamp=1626716578584&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fhas-flag%2Fdownload%2Fhas-flag-4.0.0.tgz",
+          "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=",
+          "dev": true,
+          "optional": true
+        },
+        "loader-utils": {
+          "version": "2.0.2",
+          "resolved": "https://registry.npmmirror.com/loader-utils/download/loader-utils-2.0.2.tgz?cache=0&sync_timestamp=1636687953081&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Floader-utils%2Fdownload%2Floader-utils-2.0.2.tgz",
+          "integrity": "sha1-1uO0+4GHByGuTghoqxHdY4NowSk=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^2.1.2"
+          }
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmmirror.com/supports-color/download/supports-color-7.2.0.tgz",
+          "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
+      }
+    },
     "vue-router": {
       "version": "3.4.5",
       "resolved": "https://registry.npm.taobao.org/vue-router/download/vue-router-3.4.5.tgz?cache=0&sync_timestamp=1601130992163&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-router%2Fdownload%2Fvue-router-3.4.5.tgz",

+ 1 - 1
package.json

@@ -1,5 +1,5 @@
 {
-  "name": "itube",
+  "name": "hertube",
   "version": "1.0.0",
   "private": true,
   "scripts": {

+ 2 - 2
public/index.html

@@ -5,14 +5,14 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width,initial-scale=1.0">
     <link rel="icon" href="/favicon.png">
-    <title>PornTube</title>
+    <title>HerTube</title>
     <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
 
   </head>
   <body>
     <noscript>
-      <strong>We're sorry but PornTube doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
+      <strong>We're sorry but HerTube doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
     </noscript>
     <div id="app"></div>
     <!-- built files will be auto injected -->

BIN
public/logo.png


BIN
public/logo1.png


+ 7 - 18
src/components/login-form.vue

@@ -29,10 +29,10 @@
       </v-col>
       <v-col cols="5">
         <v-text-field
-          v-model="verifyCode"
+          v-model="captcha"
           placeholder="验证码"
           label="验证码"
-          :rules="[() => verifyCode != null || '验证码不能为空']"
+          :rules="[() => captcha != null || '验证码不能为空']"
           clearable
         />
       </v-col>
@@ -57,7 +57,7 @@ export default {
       captchaUrl: '/api/user/account/captcha',
       username: '',
       password: '',
-      verifyCode: '',
+      captcha: '',
       rememberMe: false
     }
   },
@@ -65,32 +65,21 @@ export default {
     submitLog() {
       const username = this.username
       const password = this.password
-      const verifyCode = this.verifyCode
+      const captcha = this.captcha
       const rememberMe = this.rememberMe
       const user = {
         username,
         password,
-        verifyCode,
+        captcha,
         rememberMe
       }
-      if (username === '' || password === '' || verifyCode === '') {
+      if (username === '' || password === '' || captcha === '') {
         return
       }
       this.$emit('login', user)
     },
     getVerifyImage() {
-      this.captchaUrl = '/api/user/account/captcha?r=' + this.randomStr(10, 22)
-    },
-    randomStr(min, max) {
-      var returnStr = ''
-      var range = (max ? Math.round(Math.random() * (max - min)) + min : min)
-      var arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
-
-      for (var i = 0; i < range; i++) {
-        var index = Math.round(Math.random() * (arr.length - 1))
-        returnStr += arr[index]
-      }
-      return returnStr
+      this.captchaUrl = '/api/user/account/captcha'
     }
   }
 }

+ 37 - 22
src/components/player/player.vue

@@ -4,50 +4,65 @@
 
 <script>
 import DPlayer from 'dplayer'
-const Hls = require('hls.js')
+const hls = require('hls.js')
 export default {
   name: 'Play',
   props: {
-    video: {
-      type: Object,
-      default: () => {}
-    },
-    picurl: {
+    videoid: {
       type: String,
       default: ''
-    },
-    article: {
-      type: Number,
-      default: 0
     }
   },
   data() {
     return {
-      Hls,
-      videoData: this.video,
-      pic: this.picurl,
-      id: this.article
+      hls,
+      dplayer: {}
     }
   },
   mounted() {
-    console.log(this.videoData.sub)
-    this.init()
+    this.videoUrl()
   },
   methods: {
-    init() {
+    videoUrl() {
+      fetch(`/api/media/video/url/${this.videoid}`, {
+        headers: {
+          'Content-Type': 'application/json; charset=UTF-8',
+          'X-XSRF-TOKEN': this.$cookies.get('XSRF-TOKEN')
+        },
+        method: 'GET',
+        credentials: 'include'
+      }).then(response => response.json())
+        .then(json => {
+          if (json.code === 0) {
+            var coverUrl = json.data.coverUrl
+            var videoUrl = json.data.videoUrl
+            this.init(coverUrl, videoUrl)
+          } else {
+            // TODO 显示 404
+            this.$router.push('/')
+          }
+        })
+        .catch(e => {
+          return null
+        })
+    },
+    init(coverUrl, videoUrl) {
       new DPlayer({
         container: document.querySelector('#dplayer'),
         lang: 'zh-cn',
         screenshot: true,
         video: {
-          url: this.videoData.fileUrl + '?key=' + encodeURIComponent(this.videoData.key), // 'https://api.dogecloud.com/player/get.mp4?vcode=5ac682e6f8231991&userId=17&ext=.mp4',
-          pic: this.pic
+          pic: coverUrl,
+          // 'https://api.dogecloud.com/player/get.mp4?vcode=5ac682e6f8231991&userId=17&ext=.mp4',
+          // url: this.videoData.videoUrl + '?key=' + encodeURIComponent(this.videoData.key),
+          // url: this.videoData.videoUrl,
+          url: videoUrl
         },
         logo: '/logo.png',
         danmaku: {
-          id: this.videoData.id,
-          api: '/api/danmaku/',
-          token: 'mjmnb',
+          videoId: 'daljfa',
+          api: '/api/media/danmaku/',
+          token: 'hertube',
           maximum: 1000,
           // addition: ['/api/danmaku/post'],
           user: () => {

+ 4 - 5
src/components/player/video-card.vue

@@ -1,9 +1,9 @@
 <template>
   <!-- padding-left: 10px; padding-right: 10px; -->
   <div style="width: 350px">
-    <router-link :to="`/video/${videoInfo.id}`">
+    <router-link :to="`/video/${videoInfo.videoId}`">
       <v-img
-        :src="videoInfo.imgUrl"
+        :src="videoInfo.coverUrl"
         outlined
         aspect-ratio="1.77"
       />
@@ -22,10 +22,10 @@
         </p>
         <p style="font-size: 10px; color: #606060;">
           {{ videoInfo.viewCount }} 观看 <span v-html="`&nbsp;&nbsp;`" />
-          {{ videoInfo.danmakuCount }} 条弹幕 <br>
+          {{ videoInfo.danmukuCount }} 条弹幕 <br>
           <router-link :to="`/user/${videoInfo.userId}`"> {{ videoInfo.username }}</router-link>
           <br>
-          <span v-text="TimeUtil.timeToNowStrning(videoInfo.createTime)" />
+          <span v-text="TimeUtil.timeToNowStrning(videoInfo.pubDate)" />
         </p>
       </v-col>
     </v-row>
@@ -55,5 +55,4 @@ export default {
 </script>
 
 <style>
-
 </style>

+ 1 - 12
src/components/register-from.vue

@@ -129,18 +129,7 @@ export default {
       this.$emit('register', this.registerUser)
     },
     getVerifyImage() {
-      this.captchaUrl = '/api/user/account/captcha?r=' + this.randomStr(10, 22)
-    },
-    randomStr(min, max) {
-      var returnStr = ''
-      var range = (max ? Math.round(Math.random() * (max - min)) + min : min)
-      var arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
-
-      for (var i = 0; i < range; i++) {
-        var index = Math.round(Math.random() * (arr.length - 1))
-        returnStr += arr[index]
-      }
-      return returnStr
+      this.captchaUrl = '/api/user/account/captcha'
     }
   }
 }

+ 2 - 14
src/components/setting/user-password-setting.vue

@@ -111,7 +111,7 @@ export default {
   },
   methods: {
     getVerifyImage() {
-      this.captchaUrl = '/api/user/account/captcha?r=' + this.randomStr(10, 22)
+      this.captchaUrl = '/api/user/account/captcha'
     },
     save() {
       if (this.passoword.oldPassword === '') {
@@ -149,22 +149,10 @@ export default {
         .catch(e => {
           return null
         })
-    },
-      randomStr(min, max) {
-          var returnStr = ''
-          var range = (max ? Math.round(Math.random() * (max - min)) + min : min)
-          var arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
-
-          for (var i = 0; i < range; i++) {
-              var index = Math.round(Math.random() * (arr.length - 1))
-              returnStr += arr[index]
-          }
-          return returnStr
-      }
+    }
   }
 }
 </script>
 
 <style>
-
 </style>

+ 1 - 1
src/components/upload/filepond-image.vue

@@ -64,7 +64,7 @@ export default {
       videMessage: {},
       myFiles: [],
       server: {
-        url: '/api/upload/video',
+        url: '/api/file/upload/video',
         process: {
           headers: {
             'X-XSRF-TOKEN': this.$cookies.get('XSRF-TOKEN')

+ 4 - 2
src/components/upload/filepond-upload.vue

@@ -53,14 +53,16 @@ export default {
       videMessage: {},
       myFiles: [],
       server: {
-        url: '/api/upload/video',
+        url: '/api/file/upload/video',
         process: {
           headers: {
             'X-XSRF-TOKEN': this.$cookies.get('XSRF-TOKEN')
           },
           onload(response) {
+            var resp = JSON.parse(response)
+            console.log('response -> ' + resp)
             // 返回上传数据
-            videMessage = JSON.parse(response)
+            videMessage = resp
           }
         }
       }

+ 35 - 37
src/components/upload/upload-video.vue

@@ -24,10 +24,12 @@
         <v-row justify="center">
           <v-col cols="5">
             <v-card outlined>
-              <v-img :src="article.imgUrl" aspect-ratio="1.77" contain max-height="150" alt="封面图,推荐16:9" />
+              <v-img :src="videoInfo.coverUrl" aspect-ratio="1.77" contain max-height="150" alt="封面图,推荐16:9" />
             </v-card>
           </v-col>
 
+          <!--
+          TODO 现阶段由系统生成封面
           <v-col cols="5">
             <v-file-input
               :rules="rules"
@@ -40,7 +42,7 @@
             <v-btn color="primary" @click="uploadFile">
               上传
             </v-btn>
-          </v-col>
+          </v-col>-->
         </v-row>
         <v-row justify="center">
           <v-col cols="5">
@@ -61,18 +63,18 @@
         <v-row justify="center">
           <v-col cols="10">
             <v-text-field
-              v-model="article.title"
+              v-model="videoInfo.title"
               placeholder="标题"
               label="标题(50字以内)"
               clearable
-              :rules="[() => article.title != null || '标题不能为空']"
+              :rules="[() => videoInfo.title != null || '标题不能为空']"
             />
           </v-col>
         </v-row>
         <v-row justify="center">
           <v-col cols="10">
             <v-textarea
-              v-model="article.describe"
+              v-model="videoInfo.desc"
               label="简介(200字以内)"
               clearable
               placeholder="填写更全面的视频信息,让更多的人找到你!"
@@ -82,7 +84,7 @@
         <v-row justify="center">
           <v-col cols="10">
             <v-combobox
-              v-model="article.tag"
+              v-model="videoInfo.tags"
               label="添加标签让更多人找到你(最多6个)"
               multiple
               chips
@@ -130,14 +132,14 @@ export default {
       rules: [
         value => !value || value.size < 2000000 || 'Avatar size should be less than 2 MB!'
       ],
-      article: {
+      videoInfo: {
+        fileId: '',
         title: '',
-        describe: '',
-        imgUrl: '',
+        desc: '',
+        coverUrl: '',
+        duration: 0,
         category: -1,
-        tag: [],
-        video: {},
-        imageId: ''
+        tags: []
       },
       categoryMap: {
         Set: function(key, value) { this[key] = value },
@@ -158,32 +160,32 @@ export default {
   },
   methods: {
     publis() {
-      if (!this.article.video.id) {
+      if (!this.videoInfo.fileId) {
         this.message = '你还没有上传视频'
         this.showMessage = true
         return
       }
-      if (this.article.title === '' || this.imgUrl === '' || this.article.tag.length === 0 || this.article.category === -1) {
+      if (this.videoInfo.title === '' || this.coverUrl === '' || this.videoInfo.tags.length === 0 || this.videoInfo.category === -1) {
         this.message = '标题,封面,标签,分区不能为空'
         this.showMessage = true
         return
       }
-      if (this.article.tag.length > 6) {
+      if (this.videoInfo.tags.length > 6) {
         this.message = '标签超过6个'
         this.showMessage = true
         return
       }
-      fetch(`/api/article/video`, {
+      fetch(`/api/media/video/submit`, {
         headers: {
           'Content-Type': 'application/json; charset=UTF-8',
           'X-XSRF-TOKEN': this.$cookies.get('XSRF-TOKEN')
         },
         method: 'POST',
         credentials: 'include',
-        body: JSON.stringify(this.article)
+        body: JSON.stringify(this.videoInfo)
       }).then(response => response.json())
         .then(json => {
-          if (json.status === 200) {
+          if (json.code === 0) {
             this.message = '投稿成功,等待审核通过后你就可以看到你的视频了'
             this.showMessage = true
             this.$router.push('/studio')
@@ -196,20 +198,19 @@ export default {
         .catch(e => {
           return null
         })
-
-      console.log(this.article)
     },
     setFile(value) {
       this.files = []
       this.files.push(value)
     },
     videoUploadSuccess(value) {
-      // console.log(value)
-      if (value.status === 200) {
-        //
-        this.article.video = value.data[0]
-        this.setTitle(value.data[0].fileOriginalName)
-        this.message = '上传视频成功'
+      if (value.code === 0) {
+        this.videoInfo.fileId = value.data[0].fileId
+        this.setTitle(value.data[0].filename)
+        this.videoInfo.duration = value.data[0].duration
+        this.videoInfo.coverUrl = 'http://localhost:8000' + value.data[0].coverUrl
+
+        this.message = '视频上传成功'
         this.showMessage = true
       } else {
         this.message = '上传出现异常,请重试!' + value.message
@@ -218,9 +219,9 @@ export default {
     },
     setTitle(title) {
       if (title.length > 50) {
-        this.article.title = title.substring(0, 50)
+        this.videoInfo.title = title.substring(0, 50)
       } else {
-        this.article.title = title
+        this.videoInfo.title = title
       }
     },
     uploadFile() {
@@ -233,7 +234,7 @@ export default {
       for (let i = 0; i < this.files.length; i++) {
         formData.append('file[]', this.files[i])
       }
-      fetch(`/api/upload/photo`, {
+      fetch(`/api/file/upload/image`, {
         headers: {
           'X-XSRF-TOKEN': this.$cookies.get('XSRF-TOKEN')
         },
@@ -242,10 +243,8 @@ export default {
         body: formData
       }).then(response => response.json())
         .then(json => {
-          if (json.status === 200) {
-            //
-            this.article.imageId = json.data[0].id
-            this.article.imgUrl = json.data[0].fileUrl
+          if (json.code === 0) {
+            this.videoInfo.coverUrl = 'http://localhost:8000' + json.data[0].url
           } else {
             this.message = '上传失败,请重试!' + json.message
             this.showMessage = true
@@ -256,7 +255,7 @@ export default {
         })
     },
     getCategory() {
-      fetch(`/api/category/list`, {
+      fetch(`/api/media/video/category`, {
         headers: {
           'Content-Type': 'application/json; charset=UTF-8',
           'X-XSRF-TOKEN': this.$cookies.get('XSRF-TOKEN')
@@ -279,7 +278,7 @@ export default {
     getMainCategory(value) {
       this.categoryChildren = []
       this.nowCategory = this.categoryMap.Get(value)
-      this.article.category = this.nowCategory.id
+      this.videoInfo.category = this.nowCategory.id
 
       const c = this.nowCategory.children
       if (c) {
@@ -292,7 +291,7 @@ export default {
       const c = this.nowCategory.children
       for (let i = 0; i < c.length; i++) {
         if (c[i].name === value) {
-          this.article.category = c[i].id
+          this.videoInfo.category = c[i].id
         }
       }
     }
@@ -301,5 +300,4 @@ export default {
 </script>
 
 <style>
-
 </style>

+ 1 - 1
src/layout/index.vue

@@ -114,7 +114,7 @@ export default {
   },
   data: () => ({
     userInfo: {},
-    drawer: false,
+    drawer: true,
     items: [
       { icon: 'mdi-home', text: '首页', link: '/' },
       { icon: 'mdi-trending-up', text: '时下流行', link: '/hot' },

+ 0 - 1
src/layout/studio.vue

@@ -138,7 +138,6 @@ export default {
       { icon: 'mdi-upload', text: '投稿', link: '/studio/upload' },
       { icon: 'mdi-database', text: '数据分析', link: '/studio/data' },
       { icon: 'mdi-account-multiple', text: '粉丝管理', link: '/studio/fans' }
-
       //   { icon: 'mdi-history', text: '历史记录', link: '/history' },
       //   { icon: 'mdi-playlist-play', text: '稍后再看', link: '/playlist' }
     ],

+ 7 - 0
src/plugins/loading/index.js

@@ -0,0 +1,7 @@
+import loading from './loading'
+
+export default {
+  install(Vue) {
+    Vue.directive('loading', loading)
+  }
+}

+ 41 - 0
src/plugins/loading/loading.js

@@ -0,0 +1,41 @@
+import Vue from 'vue'
+import Loading from './loading.vue'
+
+const Mask = Vue.extend(Loading)
+
+const toggleLoading = (el, binding) => {
+  if (binding.value) {
+    Vue.nextTick(() => {
+      el.instance.visible = true
+      insertDom(el, el, binding)
+    })
+  } else {
+    el.instance.visible = false
+  }
+}
+
+const insertDom = (parent, el) => {
+  parent.appendChild(el.mask)
+}
+
+export default {
+  bind: function(el, binding) {
+    const mask = new Mask({
+      el: document.createElement('div'),
+      data() {}
+    })
+    el.instance = mask
+    el.mask = mask.$el
+    el.maskStyle = {}
+    binding.value && toggleLoading(el, binding)
+  },
+  update: function(el, binding) {
+    if (binding.oldValue !== binding.value) {
+      toggleLoading(el, binding)
+    }
+  },
+  unbind: function(el, binding) {
+    el.instance && el.instance.$destroy()
+    el = null
+  }
+}

+ 36 - 0
src/plugins/loading/loading.vue

@@ -0,0 +1,36 @@
+<template>
+  <div v-show="visible" class="loading-wrap">
+    <ul class="loading-box">
+      加载中...
+    </ul>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      visible: false
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+  .loading-wrap {
+    position: absolute;
+    left: 0;
+    right: 0;
+    top: 0;
+    bottom: 0;
+    background: rgba(255, 255, 255, 0.5);
+  }
+  .loading-box {
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    height: 60px;
+    width: 60px;
+    margin-top: -30px;
+    margin-left: -30px;
+  }
+</style>

+ 7 - 7
src/router/index.js

@@ -10,37 +10,37 @@ const routes = [
     path: '/',
     name: 'Index',
     component: Index,
-    meta: { title: 'PornTube' },
+    meta: { title: 'HerTube' },
     children: [
       {
         path: '/',
         name: 'Index',
         component: Home,
-        meta: { title: 'PornTube' }
+        meta: { title: 'HerTube' }
       },
       {
         path: '/hot',
         name: 'Hot',
         component: () => import('@/views/home/hot.vue'),
-        meta: { title: 'PornTube 时下流行' }
+        meta: { title: 'HerTube 时下流行' }
       },
       {
         path: '/subscribe',
         name: 'Subscribe',
         component: () => import('@/views/home/subscribe.vue'),
-        meta: { title: 'PornTube 订阅' }
+        meta: { title: 'HerTube 订阅' }
       },
       {
         path: '/history',
         name: 'History',
         component: () => import('@/views/home/history.vue'),
-        meta: { title: 'PornTube 播放历史' }
+        meta: { title: 'HerTube 播放历史' }
       },
       {
         path: '/playlist',
         name: 'Playlist',
         component: () => import('@/views/home/playlist.vue'),
-        meta: { title: 'PornTube 稍后再看' }
+        meta: { title: 'HerTube 稍后再看' }
       },
       {
         path: '/video/:id',
@@ -218,7 +218,7 @@ router.beforeEach((to, from, next) => {
     document.title = to.meta.title
   }
   if (checkPower.updateUserRole(router.app.$options.store.state.userInfo)) {
-    router.app.$options.store.state.userInfo.userRoleEntity.role = 'ROLE_USER'
+    router.app.$options.store.state.userInfo.role = 'ROLE_USER'
     router.app.$options.store.commit('setUserInfo', router.app.$options.store.state.userInfo)
   }
 

+ 1 - 1
src/store/index.js

@@ -6,7 +6,7 @@ Vue.use(Vuex)
 export default new Vuex.Store({
   state: {
     webInfo: {
-      // name: 'PornTube',
+      // name: 'HerTube',
       // openNoVipLimit: 1,
       // noVipViewCount: 5,
       // logoUrl: '/logo.png',

+ 8 - 8
src/utils/check-power.vue

@@ -1,28 +1,28 @@
 <script>
 
 function checkPower(userInfo) {
-  if (userInfo.userRoleEntity.role === 'ROLE_ADMIN') {
+  if (userInfo.role === 'ROLE_ADMIN') {
     return 'admin'
   }
-  if (userInfo.userRoleEntity.role === 'ROLE_VIP') {
-    if (userInfo.userRoleEntity.vipStopTime < new Date().getTime()) {
+  if (userInfo.role === 'ROLE_VIP') {
+    if (userInfo.vipStopTime < new Date().getTime()) {
       return 'user'
     }
     return 'vip'
   }
-  if (userInfo.userRoleEntity.role === 'ROLE_USER') {
+  if (userInfo.role === 'ROLE_USER') {
     return 'user'
   }
 }
 
 function checkVip(userInfo) {
-  if (userInfo.userRoleEntity.role === 'ROLE_VIP') {
-    if (userInfo.userRoleEntity.vipStopTime < new Date().getTime()) {
+  if (userInfo.role === 'ROLE_VIP') {
+    if (userInfo.vipStopTime < new Date().getTime()) {
       return false
     }
     return true
   }
-  if (userInfo.userRoleEntity.role === 'ROLE_ADMIN') {
+  if (userInfo.role === 'ROLE_ADMIN') {
     return true
   }
   return false
@@ -32,7 +32,7 @@ function updateUserRole(userInfo) {
   if (userInfo === null) {
     return false
   }
-  if (userInfo.userRoleEntity.role === 'ROLE_VIP' && userInfo.userRoleEntity.vipStopTime < new Date().getTime()) {
+  if (userInfo.role === 'ROLE_VIP' && userInfo.vipStopTime < new Date().getTime()) {
     return true
   }
   return false

+ 3 - 3
src/views/home/index.vue

@@ -64,7 +64,7 @@ export default {
   },
   methods: {
     getVideoList() {
-      fetch(`/api/media/article/home/list?page=${this.page}&limit=${this.size}`, {
+      fetch(`/api/media/video/post/preview?page=${this.page}&size=${this.size}`, {
         headers: {
           'Content-Type': 'application/json; charset=UTF-8',
           'X-XSRF-TOKEN': this.$cookies.get('XSRF-TOKEN')
@@ -74,8 +74,8 @@ export default {
       }).then(response => response.json())
         .then(json => {
           this.videoList = json.data.list
-          this.page = json.data.currPage
-          this.length = json.data.totalPage
+          this.page = json.data.totalSize
+          this.length = json.data.totalSize
         })
         .catch(e => {
           return null

+ 1 - 1
src/views/user/index.vue

@@ -25,7 +25,7 @@
           </h2>
         </v-col>
         <v-col
-          v-if="this.$store.state.userInfo && this.$store.state.userInfo.id == id"
+          v-if="this.$store.state.userInfo && this.$store.state.userInfo.id === id"
           cols="6"
           md="4"
           class="hidden-sm-and-down ml-0 pl-4"

+ 21 - 16
src/views/video/video.vue

@@ -3,7 +3,7 @@
     <v-container fill-height fluid style="padding-bottom: 0px;">
       <v-row>
         <v-col style="padding-bottom: 0px;">
-          <DPlayer :article="parseInt(id)" :video="videoData.video[0]" :picurl="videoData.imgUrl" />
+          <VideoPlayer :videoid="videoId" />
         </v-col>
       </v-row>
     </v-container>
@@ -17,18 +17,20 @@
           </v-row>
           <v-row>
             <v-col style="color: #999;font-size: 12px;padding-top: 0px;">
+              <!--
+              TODO 暂时不显示分类
               <router-link v-if="videoData.childrenCategory.fatherId !== 0" :to="`/v/${videoData.fatherCategory.id}`" class="category-link">
                 <span v-text="videoData.fatherCategory.name" />
               </router-link>
               /
               <router-link :to="`/v/${videoData.childrenCategory.id}`" class="category-link">
                 <span v-text="videoData.childrenCategory.name" />
-              </router-link>
+              </router-link>-->
               <span v-html="'&nbsp;&nbsp;&nbsp;&nbsp;'" />
               发布于:
-              <span v-text="TimeUtil.renderTime(videoData.createTime)" />
+              <span v-text="TimeUtil.renderTime(videoData.pubDate)" />
               <br>
-              <span v-text="videoData.viewCount" /> 次观看 <span v-html="'&nbsp;&nbsp;&nbsp;&nbsp;'" /> <span v-text="videoData.danmakuCount" /> 弹幕
+              <span v-text="videoData.viewCount" /> 次观看 <span v-html="'&nbsp;&nbsp;&nbsp;&nbsp;'" /> <span v-text="videoData.danmukuCount" /> 弹幕
             </v-col>
           </v-row>
           <v-divider />
@@ -45,13 +47,13 @@
                 <span v-text="videoData.username" />
               </router-link>
               <span v-html="'&nbsp;&nbsp;&nbsp;&nbsp;'" />
-              <span style="color: #999;font-size: 12px;" v-text="videoData.introduction" /><span v-html="'&nbsp;&nbsp;&nbsp;&nbsp;'" />
+              <span style="color: #999;font-size: 12px;" v-text="videoData.intro" /><span v-html="'&nbsp;&nbsp;&nbsp;&nbsp;'" />
               <v-btn small outlined color="primary">
                 <span>关注</span><span v-html="'&nbsp;&nbsp;'" />
-                <span v-text="videoData.followCount" />
+                <span v-text="videoData.followerCount" />
               </v-btn><br>
               <br>
-              <span v-text="videoData.describes" />
+              <span v-text="videoData.desc" />
             </v-col>
           </v-row>
           <v-divider />
@@ -76,7 +78,7 @@
                 v-on="on"
               >
                 <v-icon>mdi-thumb-up</v-icon>
-                <span v-text="videoData.likeCount" />
+                <span v-text="videoData.thumbUpCount" />
               </v-btn>
             </template>
             <span>顶一下</span>
@@ -91,7 +93,7 @@
                 v-on="on"
               >
                 <v-icon>mdi-thumb-down</v-icon>
-                <span v-text="videoData.dislikeCount" />
+                <span v-text="videoData.thumbDownCount" />
               </v-btn>
             </template>
             <span>踩一下</span>
@@ -112,32 +114,35 @@
 </template>
 
 <script>
-import DPlayer from '@/components/player/player.vue'
+import VideoPlayer from '@/components/player/player.vue'
 import TimeUtil from '@/utils/time-util.vue'
 import Comment from '@/components/comment/video-comment.vue'
 
 export default {
   name: 'Video',
   components: {
-    DPlayer,
+    VideoPlayer,
     Comment
   },
   data() {
     return {
       score: 0,
       TimeUtil,
-      id: 0,
+      videoId: '0',
       videoData: {},
       windowSize: {
-
       },
       colsWidth: 8
     }
   },
   created() {
-    this.id = this.$route.params.id
+    console.log('1.########################')
+    // 获取 url 上的参数
+    this.videoId = this.$route.params.id
+    // 请求后端获取数据
     this.videoInfo()
     this.onResize()
+    console.log('2.########################')
   },
   methods: {
     // 控制页面大小
@@ -150,7 +155,7 @@ export default {
       }
     },
     videoInfo() {
-      fetch(`/api/article/video/${this.id}`, {
+      fetch(`/api/media/video/post/${this.videoId}`, {
         headers: {
           'Content-Type': 'application/json; charset=UTF-8',
           'X-XSRF-TOKEN': this.$cookies.get('XSRF-TOKEN')
@@ -159,7 +164,7 @@ export default {
         credentials: 'include'
       }).then(response => response.json())
         .then(json => {
-          if (json.status === 200 && json.data.isShow) {
+          if (json.code === 0) {
             this.videoData = json.data
             document.title = json.data.title
           } else {

+ 1 - 1
src/views/vip/index.vue

@@ -35,7 +35,7 @@
           </v-img>
 
           <v-card-text class="text--primary">
-            <div>VIP到期时间: <strong>{{ TimeUtil.renderTime(this.$store.state.userInfo.userRoleEntity.vipStopTime) }}</strong></div>
+            <div>VIP到期时间: <strong>{{ TimeUtil.renderTime(this.$store.state.userInfo.vipStopTime) }}</strong></div>
             <div>剩余观看次数:<strong> ∞ </strong></div>
           </v-card-text>
 

+ 1 - 1
vue.config.js

@@ -4,7 +4,7 @@ function resolve(dir) {
   return path.join(__dirname, dir)
 }
 
-const name = 'PornHub'
+const name = 'HerTube'
 
 module.exports = {
   productionSourceMap: false,