Procházet zdrojové kódy

解决了一些问题

reghao před 4 roky
rodič
revize
b368583ac7

+ 5 - 0
package-lock.json

@@ -3887,6 +3887,11 @@
         "randomfill": "^1.0.3"
       }
     },
+    "crypto-js": {
+      "version": "4.1.1",
+      "resolved": "https://registry.nlark.com/crypto-js/download/crypto-js-4.1.1.tgz",
+      "integrity": "sha1-nkhbzwNSEEG9hYRHhrg/t2GXNs8="
+    },
     "css-color-names": {
       "version": "0.0.4",
       "resolved": "https://registry.npm.taobao.org/css-color-names/download/css-color-names-0.0.4.tgz",

+ 1 - 0
package.json

@@ -9,6 +9,7 @@
   },
   "dependencies": {
     "core-js": "^3.6.5",
+    "crypto-js": "^4.1.1",
     "dplayer": "^1.26.0",
     "filepond": "^4.20.1",
     "filepond-plugin-file-validate-size": "^2.2.1",

+ 2 - 2
src/components/player/video-card.vue

@@ -1,6 +1,6 @@
 <template>
   <!-- padding-left: 10px; padding-right: 10px; -->
-  <div style="width: 350px">
+  <div style="width: 320px">
     <router-link :to="`/video/${videoInfo.videoId}`">
       <v-img
         :src="videoInfo.coverUrl"
@@ -17,7 +17,7 @@
         </router-link>
       </v-col>
       <v-col cols="10">
-        <p style="font-size: 20px; margin-bottom: 0px;color: black;">
+        <p style="font-size: 15px; margin-bottom: 0px;color: black;">
           <router-link :to="`/video/${videoInfo.videoId}`" style="color: black;"> {{ videoInfo.title }} </router-link>
         </p>
         <p style="font-size: 10px; color: #606060;">

+ 44 - 5
src/components/upload/filepond-upload.vue

@@ -1,6 +1,5 @@
 <template>
   <div>
-
     <file-pond
       ref="pond"
       name="file[]"
@@ -23,20 +22,18 @@
 <script>
 // Import Vue FilePond
 import vueFilePond from 'vue-filepond'
-
 // Import FilePond styles
 import 'filepond/dist/filepond.min.css'
-
 // Import FilePond plugins
 // Please note that you need to install these plugins separately
-
 // Import image preview plugin styles
 import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.min.css'
-
 // Import image preview and file type validation plugins
 import FilePondPluginFileValidateType from 'filepond-plugin-file-validate-type'
 import FilePondPluginImagePreview from 'filepond-plugin-image-preview'
 
+import CryptoJS from 'crypto-js'
+
 // Create component
 const FilePond = vueFilePond(FilePondPluginFileValidateType, FilePondPluginImagePreview)
 
@@ -77,6 +74,48 @@ export default {
     },
     success() {
       this.$emit('video', videMessage)
+    },
+    uploadCrt(param) {
+      var contractFile = param.file
+      var reader = new FileReader(); var self = this
+      var blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice
+      var chunkSize = 6 * 1024 * 1024
+      var chunks = Math.ceil(contractFile.size / chunkSize)
+      var currentChunk = 0
+      var hasher = CryptoJS.algo.SHA256.create()
+      var start = currentChunk * chunkSize
+      var end = start + chunkSize >= contractFile.size ? contractFile.size : start + chunkSize
+      reader.readAsArrayBuffer(blobSlice.call(contractFile, start, end))
+      reader.onload = function(evt) {
+        var fileStr = evt.target.result
+        var tmpWordArray = self.arrayBufferToWordArray(fileStr)
+        hasher.update(tmpWordArray)
+        currentChunk += 1
+        fileStr = null
+        tmpWordArray = null
+        if (currentChunk < chunks) {
+          var start = currentChunk * chunkSize
+          var end = start + chunkSize >= contractFile.size ? contractFile.size : start + chunkSize
+          reader.readAsArrayBuffer(blobSlice.call(contractFile, start, end))
+        }
+      }
+      reader.onloadend = function() {
+        contractFile = null
+        var hash = hasher.finalize()
+        hash.toString()// 计算结果
+        hasher = null
+        blobSlice = null
+        reader = null
+        hash = null
+      }
+    },
+    arrayBufferToWordArray(ab) {
+      var i8a = new Uint8Array(ab)
+      var a = []
+      for (var i = 0; i < i8a.length; i += 4) {
+        a.push(i8a[i] << 24 | i8a[i + 1] << 16 | i8a[i + 2] << 8 | i8a[i + 3])
+      }
+      return CryptoJS.lib.WordArray.create(a, i8a.length)
     }
   }
 }

+ 22 - 16
src/components/upload/upload-video.vue

@@ -48,14 +48,14 @@
           <v-col cols="5">
             <v-select
               :items="category"
-              label="分区"
+              label="分区"
               @change="getCategory"
             />
           </v-col>
           <v-col cols="5">
             <v-select
               :items="childCategory"
-              label="分区"
+              label="分区"
               @change="getChildCategory"
             />
           </v-col>
@@ -132,8 +132,9 @@ export default {
       rules: [
         value => !value || value.size < 2000000 || 'Avatar size should be less than 2 MB!'
       ],
+      // 提交给后端的数据
       videoInfo: {
-        videoInfoId: '',
+        infoId: '',
         title: '',
         desc: '',
         coverUrl: '',
@@ -145,7 +146,7 @@ export default {
       categoryMap: {
         Set: function(key, value) { this[key] = value },
         Get: function(key) { return this[key] },
-        Contains: function(key) { return this.Get(key) != null },
+        Contains: function(key) { return this.Get(key) !== null },
         Remove: function(key) { delete this[key] }
       },
       category: [],
@@ -166,7 +167,7 @@ export default {
         this.showMessage = true
         return
       }
-      if (this.videoInfo.title === '' || this.coverUrl === '' || this.videoInfo.tags.length === 0 || this.videoInfo.category === -1) {
+      if (this.videoInfo.title === '' || this.coverUrl === '' || this.videoInfo.tags.length === 0 || this.videoInfo.categoryId === -1) {
         this.message = '标题,封面,标签,分区不能为空'
         this.showMessage = true
         return
@@ -206,7 +207,7 @@ export default {
     },
     videoUploadSuccess(value) {
       if (value.code === 0) {
-        this.videoInfo.videoInfoId = value.data[0].videoInfoId
+        this.videoInfo.infoId = value.data[0].infoId
         this.setTitle(value.data[0].filename)
         this.videoInfo.duration = value.data[0].duration
         this.videoInfo.coverUrl = value.data[0].coverUrl
@@ -215,7 +216,12 @@ export default {
         this.message = '视频上传成功'
         this.showMessage = true
       } else {
-        this.message = '上传出现异常,请重试!' + value.message
+        // TODO 返回错误原因,网络错误或是服务端错误
+        if (value.message != null) {
+          this.message = '上传文件出现异常,请重新上传!' + value.message
+        } else {
+          this.message = '上传文件出现异常,请重新上传!'
+        }
         this.showMessage = true
       }
     },
@@ -268,7 +274,6 @@ export default {
         .then(json => {
           for (let i = 0; i < json.data.length; i++) {
             const name = json.data[i].name
-
             this.category.push(name)
             this.categoryMap.Set(name, json.data[i])
           }
@@ -277,23 +282,24 @@ export default {
           return null
         })
     },
-    getCategory(value) {
+    getCategory(name) {
+      // 重置子分区,清除前一次选择分区时留下的缓存
       this.childCategory = []
-      this.nowCategory = this.categoryMap.Get(value)
-      this.videoInfo.category = this.nowCategory.id
+      this.currentCategory = this.categoryMap.Get(name)
+      this.videoInfo.categoryId = this.currentCategory.id
 
-      const c = this.nowCategory.children
+      const c = this.currentCategory.children
       if (c) {
         for (let i = 0; i < c.length; i++) {
           this.childCategory.push(c[i].name)
         }
       }
     },
-    getChildCategory(value) {
-      const c = this.nowCategory.children
+    getChildCategory(name) {
+      const c = this.currentCategory.children
       for (let i = 0; i < c.length; i++) {
-        if (c[i].name === value) {
-          this.videoInfo.category = c[i].id
+        if (c[i].name === name) {
+          this.videoInfo.categoryId = c[i].id
         }
       }
     }

+ 23 - 44
src/views/home/index.vue

@@ -1,23 +1,5 @@
 <template>
   <v-container fill-height fluid style="padding-left: 24px; padding-right: 24px">
-    <!-- <v-row>
-      <div
-        class="d-flex flex-wrap"
-        color="grey lighten-2"
-        flat
-        tile
-      >
-        <div
-          v-for="item in videoList"
-          :key="item.id"
-          class="pa-2"
-          outlined
-          tile
-        >
-          <VideoCared :video="item" />
-        </div>
-      </div>
-    </v-row> -->
     <v-row no-gutters>
       <v-col
         v-for="item in videoList"
@@ -26,13 +8,6 @@
         <VideoCared :video="item" />
       </v-col>
     </v-row>
-    <v-row justify="center">
-      <v-pagination
-        v-model="page"
-        :length="length"
-        @input="pageChange"
-      />
-    </v-row>
   </v-container>
 </template>
 
@@ -46,25 +21,23 @@ export default {
   },
   data() {
     return {
-      videoList: [],
-      page: 1,
-      size: 24,
-      length: 0
+      videoList: []
     }
   },
+  mounted() {
+    // 监听页面是否滚动到底部
+    window.addEventListener('scroll', this.lazyLoading, true)
+  },
   created() {
-    console.log(this.$route.query.page)
-    if (this.$route.query.page === undefined) {
-      this.page = 1
-    } else {
-      this.page = this.$route.query.page
-    }
-
     this.getVideoList()
   },
+  destroyed() {
+    // 页面离开后销毁,防止切换路由后上一个页面监听scroll滚动事件会在新页面报错问题
+    window.removeEventListener('scroll', this.lazyLoading)
+  },
   methods: {
     getVideoList() {
-      fetch(`/api/media/video/post/preview?page=${this.page}&size=${this.size}`, {
+      fetch(`/api/media/video/post/recommend`, {
         headers: {
           'Content-Type': 'application/json; charset=UTF-8',
           'X-XSRF-TOKEN': this.$cookies.get('XSRF-TOKEN')
@@ -74,18 +47,24 @@ export default {
       }).then(response => response.json())
         .then(json => {
           this.videoList = json.data.list
-          this.page = json.data.totalSize
-          this.length = json.data.totalSize
         })
         .catch(e => {
           return null
         })
     },
-    pageChange(value) {
-      this.page = value
-      this.$router.push({ query: { page: this.page }})
-      this.getVideoList()
-      this.$vuetify.goTo(0)
+    // 滚动操作
+    lazyLoading() {
+      // 滚动到底部,再加载的处理事件
+      // 获取 可视区高度`、`滚动高度`、`页面高度`
+      const scrollTop = document.documentElement.scrollTop || document.body.scrollTop
+      const clientHeight = document.documentElement.clientHeight
+      const scrollHeight = document.documentElement.scrollHeight
+      // 页面滚动到底部,逻辑代码
+      if (scrollTop + clientHeight >= scrollHeight) {
+        // 事件处理
+        console.log('滚动到底部,触发')
+        this.getVideoList()
+      }
     }
   }
 }

+ 35 - 2
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;">
-          <VideoPlayer/>
+          <VideoPlayer />
         </v-col>
       </v-row>
     </v-container>
@@ -17,7 +17,9 @@
           </v-row>
           <v-row>
             <v-col style="color: #999;font-size: 12px;padding-top: 0px;">
-              <!--<router-link v-if="videoData.childrenCategory.fatherId !== 0" :to="`/v/${videoData.fatherCategory.id}`" class="category-link">
+              <!--
+              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>
               /
@@ -99,6 +101,14 @@
         </v-col>
         <v-col>
           相关视频:
+          <v-row no-gutters>
+            <v-col
+              v-for="item in videoList"
+              :key="item.id"
+            >
+              <VideoCared :video="item" />
+            </v-col>
+          </v-row>
         </v-col>
       </v-row>
     </v-container>
@@ -106,6 +116,7 @@
 </template>
 
 <script>
+import VideoCared from '@/components/player/video-card.vue'
 import VideoPlayer from '@/components/player/player.vue'
 import TimeUtil from '@/utils/time-util.vue'
 import Comment from '@/components/comment/video-comment.vue'
@@ -113,11 +124,13 @@ import Comment from '@/components/comment/video-comment.vue'
 export default {
   name: 'Video',
   components: {
+    VideoCared,
     VideoPlayer,
     Comment
   },
   data() {
     return {
+      videoList: [],
       score: 0,
       TimeUtil,
       videoId: '',
@@ -133,6 +146,7 @@ export default {
     // 请求后端获取数据
     this.videoInfo()
     this.onResize()
+    this.getSimilarVideos(this.videoId)
   },
   methods: {
     // 控制页面大小
@@ -165,6 +179,25 @@ export default {
         .catch(e => {
           return null
         })
+    },
+    // 获取和当前视频类似的其他视频
+    getSimilarVideos(videoId) {
+      fetch(`/api/media/video/post/similar?videoId=${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 => {
+          this.videoList = json.data.list
+          this.page = json.data.totalSize
+          this.length = json.data.totalSize
+        })
+        .catch(e => {
+          return null
+        })
     }
   }
 }