reghao 6 mesi fa
parent
commit
129f428593
4 ha cambiato i file con 422 aggiunte e 55 eliminazioni
  1. 31 2
      src/api/disk.js
  2. 17 4
      src/views/disk/Disk.vue
  3. 118 1
      src/views/disk/DiskAlbum.vue
  4. 256 48
      src/views/disk/DiskFile.vue

+ 31 - 2
src/api/disk.js

@@ -3,8 +3,13 @@ import { get, post } from '@/utils/request'
 const diskApi = {
   diskFileApi: '/api/content/disk/file',
   filePreviewApi: '/api/content/disk/preview',
-  ossStsApi: '/api/file/aliyun/sts_token',
-  getCamDetailApi: '/api/content/disk/cam/detail'
+  createAlbumApi: '/api/content/disk/album/create',
+  addToAlbumApi: '/api/content/disk/album/add',
+  getAlbumKeyValueApi: '/api/content/disk/album/kv',
+  getAlbumListApi: '/api/content/disk/album/list',
+  getAlbumDetailApi: '/api/content/disk/album/detail',
+  getCamDetailApi: '/api/content/disk/cam/detail',
+  getDiskChannelInfoApi: '/api/file/oss/serverinfo/file'
 }
 
 export function getDiskFile(query) {
@@ -18,3 +23,27 @@ export function getFileDetail(fileId) {
 export function getCamDetail(query) {
   return get(diskApi.getCamDetailApi, query)
 }
+
+export function getDiskChannelInfo() {
+  return post(diskApi.getDiskChannelInfoApi)
+}
+
+export function createAlbum(data) {
+  return post(diskApi.createAlbumApi, data)
+}
+
+export function addToAlbum(data) {
+  return post(diskApi.addToAlbumApi, data)
+}
+
+export function getAlbumKeyValues() {
+  return post(diskApi.getAlbumKeyValueApi)
+}
+
+export function getAlbumList() {
+  return post(diskApi.getAlbumListApi)
+}
+
+export function getAlbumDetail(albumId) {
+  return post(diskApi.getAlbumDetailApi + '/' + albumId)
+}

+ 17 - 4
src/views/disk/Disk.vue

@@ -55,13 +55,13 @@
                   <el-dropdown-item
                     icon="el-icon-s-platform"
                     class="size"
-                    @click.native="goToHome"
-                  >主站</el-dropdown-item>
+                    @click.native="backToHome"
+                  >回到主站</el-dropdown-item>
                   <el-dropdown-item
                     icon="el-icon-error"
                     class="size"
-                    @click.native="goToLogout"
-                  >退出</el-dropdown-item>
+                    @click.native="logout"
+                  >出</el-dropdown-item>
                 </el-dropdown-menu>
               </el-dropdown>
               <span
@@ -96,6 +96,19 @@ export default {
   created() {
     document.title = '网盘'
     this.user = getAuthedUser()
+  },
+  methods: {
+    backToHome() {
+      const path = '/'
+      if (this.$route.path === path) {
+        this.$router.go(0)
+        return
+      }
+      this.$router.push(path)
+    },
+    logout() {
+      this.$message.info('logout')
+    }
   }
 }
 </script>

+ 118 - 1
src/views/disk/DiskAlbum.vue

@@ -1,26 +1,143 @@
 <template>
   <div>
-    <span>Disk Album</span>
+    <el-row>
+      <el-col
+        style="padding: 5px;"
+      >
+        <el-image
+          class="img240"
+          @click.native="onCreateAlbum"
+        />
+      </el-col>
+      <el-col
+        v-for="(album, index) in dataList"
+        :key="index"
+        :md="6"
+        :sm="12"
+        :xs="12"
+        style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px"
+      >
+        <div class="imgs">
+          <el-image
+            lazy
+            fit="cover"
+            class="coverImg"
+            :src="album.coverUrl"
+            @click="getAlbum(album.albumId)"
+          />
+        </div>
+      </el-col>
+    </el-row>
+    <el-row>
+      <el-pagination
+        :small="screenWidth <= 768"
+        hide-on-single-page
+        layout="prev, pager, next"
+        :page-size="pageSize"
+        :current-page="currentPage"
+        :total="totalSize"
+        @current-change="handleCurrentChange"
+        @prev-click="handleCurrentChange"
+        @next-click="handleCurrentChange"
+      />
+    </el-row>
+
+    <el-dialog
+      :visible.sync="showCreateAlbumDialog"
+      width="30%"
+      center
+    >
+      <div>
+        <el-form ref="createAlbumForm" :model="createAlbumForm">
+          <el-form-item label="相册名" label-width="120px" prop="title">
+            <el-input
+              v-model="createAlbumForm.albumName"
+              style="margin-left: 5px"
+              clearable
+            />
+          </el-form-item>
+          <el-button
+            type="primary"
+            plain
+            size="small"
+            icon="el-icon-plus"
+            style="margin-left: 10px"
+            @click="createAlbum"
+          >
+            创建相册
+          </el-button>
+        </el-form>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
 
+import { createAlbum } from '@/api/disk'
+
 export default {
   name: 'DiskAlbum',
   data() {
     return {
+      // 屏幕宽度, 为了控制分页条的大小
+      screenWidth: document.body.clientWidth,
+      currentPage: 1,
+      pageSize: 12,
+      totalSize: 0,
+      dataList: [],
+      albumId: null,
+      showCreateAlbumDialog: false,
+      createAlbumForm: {
+        albumName: null
+      }
+    }
+  },
+  mounted() {
+    // 当窗口宽度改变时获取屏幕宽度
+    window.onresize = () => {
+      return () => {
+        window.screenWidth = document.body.clientWidth
+        this.screenWidth = window.screenWidth
+      }
     }
   },
   created() {
     this.getData()
   },
   methods: {
+    handleCurrentChange(pageNumber) {
+      this.currentPage = pageNumber
+      this.dataList = []
+      this.getData()
+      // 回到顶部
+      scrollTo(0, 0)
+    },
     getData() {
+    },
+    onCreateAlbum() {
+      this.showCreateAlbumDialog = true
+    },
+    createAlbum() {
+      this.showCreateAlbumDialog = false
+      createAlbum(this.createAlbumForm).then(resp => {
+        this.$message.info(resp.msg)
+      })
+    },
+    getAlbum(albumId) {
+      this.$message.info('get ' + albumId)
     }
   }
 }
 </script>
 
 <style scoped lang="scss">
+.img320 {
+  width: 320px;
+  height: 240px
+}
+.img240 {
+  width: 240px;
+  height: 180px
+}
 </style>

+ 256 - 48
src/views/disk/DiskFile.vue

@@ -2,17 +2,7 @@
   <div style="padding-right: 5px">
     <el-row style="padding: 5px">
       <el-dropdown style="padding-right: 5px">
-        <el-button size="small" type="primary" icon="el-icon-upload" round>上传</el-button>
-        <el-dropdown-menu slot="dropdown">
-          <el-dropdown-item
-            icon="el-icon-files"
-            @click.native="onUploadFile"
-          >上传文件</el-dropdown-item>
-          <el-dropdown-item
-            icon="el-icon-folder"
-            @click.native="onUploadFolder"
-          >上传文件夹</el-dropdown-item>
-        </el-dropdown-menu>
+        <el-button size="small" type="primary" icon="el-icon-upload" round @click="onClickUpload">上传</el-button>
       </el-dropdown>
       <el-button size="small" type="primary" icon="el-icon-folder-add" round @click="onCreateFolder">新建文件夹</el-button>
       <el-input
@@ -84,6 +74,9 @@
           label="修改时间"
         />
       </el-table>
+      <div style="margin-top: 20px">
+        <el-button v-if="selectedTable.length !== 0" @click="addToAlbum">添加到相册</el-button>
+      </div>
       <el-pagination
         background
         :small="screenWidth <= 768"
@@ -99,7 +92,7 @@
 
     <el-dialog
       :visible.sync="showPreviewDialog"
-      :before-close="handleClose"
+      :before-close="handlePreviewClose"
       width="100%"
       center
     >
@@ -144,11 +137,73 @@
         </div>
       </el-card>
     </el-dialog>
+    <el-dialog
+      :visible.sync="showCreateFolderDialog"
+      width="30%"
+      center
+    >
+      <div>
+        <el-form ref="createFolderForm" :model="createFolderForm">
+          <el-form-item label="当前文件夹" label-width="120px" prop="title">
+            <el-input
+              v-model="createFolderForm.path"
+              style="margin-left: 5px"
+              readonly
+            />
+          </el-form-item>
+          <el-form-item label="新文件夹名" label-width="120px" prop="title">
+            <el-input
+              v-model="createFolderForm.folderName"
+              style="margin-left: 5px"
+              clearable
+            />
+          </el-form-item>
+          <el-button
+            type="primary"
+            plain
+            size="small"
+            icon="el-icon-plus"
+            style="margin-left: 10px"
+            @click="createFolder"
+          >
+            创建文件夹
+          </el-button>
+        </el-form>
+      </div>
+    </el-dialog>
+    <el-dialog
+      :visible.sync="showUploadDialog"
+      :before-close="handleUploadClose"
+      :close-on-click-modal="false"
+      width="50%"
+      center
+    >
+      <div>
+        <uploader
+          v-if="options !== null"
+          class="uploader-example"
+          :options="options"
+          :auto-start="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>
+    </el-dialog>
   </div>
 </template>
 
 <script>
-import { getDiskFile, getFileDetail } from '@/api/disk'
+import { addToAlbum, getAlbumKeyValues, getDiskChannelInfo, getDiskFile, getFileDetail } from '@/api/disk'
+import { hashFile } from '@/utils/functions'
 
 export default {
   name: 'DiskFile',
@@ -160,7 +215,7 @@ export default {
       pageSize: 10,
       totalSize: 0,
       dataList: [],
-      // 所有文件的对话框被选中
+      // 对话框被选中的文件
       selectedTable: [],
       inputData: '',
       showPreviewDialog: false,
@@ -176,8 +231,30 @@ export default {
       queryForm: {
         pn: this.currentPage,
         path: '/',
-        fileType: null,
-        filename: null
+        fileType: null
+      },
+      // ****************************************************************************************************************
+      showCreateFolderDialog: false,
+      createFolderForm: {
+        path: '/',
+        folderName: null
+      },
+      // ****************************************************************************************************************
+      showAddToAlbumUploadDialog: false,
+      albumKeyValues: [],
+      // ****************************************************************************************************************
+      showUploadDialog: false,
+      options: {
+        target: '',
+        // 分块大小 10MB
+        chunkSize: 1024 * 1024 * 10,
+        // 失败自动重传次数
+        maxChunkRetries: 3,
+        fileParameterName: 'file',
+        testChunks: true
+      },
+      attrs: {
+        accept: '*'
       }
     }
   },
@@ -195,46 +272,121 @@ export default {
     this.getData()
   },
   methods: {
-    handleClose() {
-      this.showPreviewDialog = false
-      this.fileDetail = null
-      this.fileType = 0
+    // ****************************************************************************************************************
+    onFileAdded(file) {
+      if (file.file.size > 1024 * 1024 * 1024 * 20) {
+        file.cancel()
+        this.$notify({
+          title: '提示',
+          message: '文件应小于 20GB',
+          type: 'warning',
+          duration: 3000
+        })
+        return
+      }
+      this.setTitle(file.file.name)
+      this.processVideo(file.file)
+
+      file.pause()
+      hashFile(file.file).then(result => {
+        this.startUpload(result.sha256sum, file)
+      })
     },
-    handleCurrentChange(pageNumber) {
-      this.currentPage = pageNumber
-      this.queryForm.pn = this.currentPage
-      this.getData()
-      // 回到顶部
-      scrollTo(0, 0)
+    startUpload(sha256sum, file) {
+      file.uniqueIdentifier = sha256sum
+      file.resume()
     },
-    getData() {
-      getDiskFile(this.queryForm).then(resp => {
+    onFileProgress(rootFile, file, chunk) {
+    },
+    onFileSuccess(rootFile, file, response, chunk) {
+      const res = JSON.parse(response)
+      if (res.code === 0) {
+        const resData = res.data
+        this.form.videoFileId = resData.uploadId
+        this.$notify({
+          title: '提示',
+          message: '视频已上传',
+          type: 'warning',
+          duration: 3000
+        })
+      } else {
+        this.$notify({
+          title: '提示',
+          message: '视频文件上传失败',
+          type: 'warning',
+          duration: 3000
+        })
+      }
+    },
+    onFileError(rootFile, file, response, chunk) {
+      this.$notify({
+        title: '提示',
+        message: '视频文件上传错误',
+        type: 'warning',
+        duration: 3000
+      })
+    },
+    handleUploadClose() {
+      this.showUploadDialog = false
+    },
+    onClickUpload() {
+      this.showUploadDialog = true
+      getDiskChannelInfo().then(resp => {
         if (resp.code === 0) {
           const respData = resp.data
-          this.pathList = respData.pathList
-          this.dataList = respData.pageList.list
-          this.totalSize = respData.pageList.totalSize
-          if (this.pathList.length === 0) {
-            this.pathList.push({ path: '/disk', name: '全部文件' })
+          this.form.channelCode = respData.channelCode
+          this.options = {
+            target: respData.ossUrl,
+            // 分块大小 10MB
+            chunkSize: 1024 * 1024 * 10,
+            // 失败自动重传次数
+            maxChunkRetries: 3,
+            fileParameterName: 'file',
+            testChunks: true,
+            // 服务器分片校验函数, 秒传及断点续传基础
+            checkChunkUploadedByResponse: function(chunk, message) {
+              const objMessage = JSON.parse(message)
+              const respData = objMessage.data
+              if (respData.skipUpload) {
+                return true
+              }
+              return (respData.uploaded || []).indexOf(chunk.offset + 1) >= 0
+            },
+            query: (file, chunk) => {
+              return {
+                channelCode: respData.channelCode,
+                multiparts: ''
+              }
+            },
+            headers: {
+              Authorization: 'Bearer ' + respData.token
+            },
+            withCredentials: false
           }
+
+          this.showUploadDialog = true
+        } else {
+          this.$notify({
+            title: '提示',
+            message: '获取 OSS 服务器地址失败, 暂时无法上传视频文件',
+            type: 'error',
+            duration: 3000
+          })
         }
+      }).catch(error => {
+        this.$notify({
+          title: '获取 OSS 服务器地址失败, 暂时无法上传视频文件',
+          message: error.message,
+          type: 'warning',
+          duration: 3000
+        })
       })
     },
-    // 处理表格被选中
-    handleTableSectionChange(val) {
-      this.selectedTable = val
-    },
-    onUploadFile() {
-      this.$message.info('upload file')
-    },
-    onUploadFolder() {
-      this.$message.info('upload folder')
-    },
-    onCreateFolder() {
-      this.$message.info('create folder')
-    },
-    onSearchFile() {
-      this.$message.info('search file')
+    // ****************************************************************************************************************
+    handlePreviewClose() {
+      this.showPreviewDialog = false
+      this.fileDetail = null
+      this.fileType = 0
     },
     onClickFilename(row) {
       this.fileType = row.fileType
@@ -259,6 +411,62 @@ export default {
           }
         })
       }
+    },
+    // ****************************************************************************************************************
+    onCreateFolder() {
+      this.showCreateFolderDialog = true
+    },
+    createFolder() {
+      console.log(this.createFolderForm)
+      this.showCreateFolderDialog = false
+    },
+    // ****************************************************************************************************************
+    handleCurrentChange(pageNumber) {
+      this.currentPage = pageNumber
+      this.queryForm.pn = this.currentPage
+      this.getData()
+      // 回到顶部
+      scrollTo(0, 0)
+    },
+    getData() {
+      getDiskFile(this.queryForm).then(resp => {
+        if (resp.code === 0) {
+          const respData = resp.data
+          const namePathList = respData.namePathList
+          const pageList = respData.pageList
+
+          this.dataList = pageList.list
+          this.totalSize = pageList.totalSize
+          if (this.pathList.length === 0) {
+            this.pathList.push({ path: '/disk', name: '全部文件' })
+          } else {
+            for (const namePath of namePathList) {
+              this.pathList.push({ path: '/disk?path=' + namePath.path, name: namePath.name })
+            }
+          }
+        }
+      })
+    },
+    // 处理表格被选中
+    handleTableSectionChange(val) {
+      this.selectedTable = val
+    },
+    addToAlbum() {
+      this.$message.info('addToAlbum')
+      getAlbumKeyValues().then(resp => {
+        if (resp.code === 0) {
+          this.albumKeyValues = resp.data
+        }
+      })
+
+      console.log(this.selectedTable)
+      const jsonData = {}
+      addToAlbum(jsonData).then(resp => {
+        this.$message.info(resp.msg)
+      })
+    },
+    onSearchFile() {
+      this.$message.info('search file')
     }
   }
 }