Просмотр исходного кода

添加 PublishFile.vue 用于上传文件测试

reghao 2 лет назад
Родитель
Сommit
612908e9fa

+ 0 - 35
package-lock.json

@@ -7645,36 +7645,6 @@
       "dev": true,
       "optional": true
     },
-    "filepond": {
-      "version": "4.30.4",
-      "resolved": "https://registry.npmmirror.com/filepond/-/filepond-4.30.4.tgz",
-      "integrity": "sha512-FCwsMvG9iiEs6uobdDrTaKsCgsqys0NuLgPPD8n37AYVYBiiDkrPkk9MSIU5rT2FahYcL1bScYI9huIPtlzqyA=="
-    },
-    "filepond-plugin-file-validate-size": {
-      "version": "2.2.8",
-      "resolved": "https://registry.npmmirror.com/filepond-plugin-file-validate-size/-/filepond-plugin-file-validate-size-2.2.8.tgz",
-      "integrity": "sha512-yzb8scATmkWqPTP7oKQz6L8WwJm6Xmgc/fuq6DFGRaLz0I7372BUvBsxagBk/hypMIjvieNzhggm33Y60x3rcw=="
-    },
-    "filepond-plugin-file-validate-type": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmmirror.com/filepond-plugin-file-validate-type/-/filepond-plugin-file-validate-type-1.2.8.tgz",
-      "integrity": "sha512-UBTqIWbk5+5R0GBELI8svu01MHWjFSLfc9DfCMvFtHKXLdJMxY1p37ChC4YKQjhfODaTuvLnNVRsukMGMFZBBg=="
-    },
-    "filepond-plugin-image-edit": {
-      "version": "1.6.3",
-      "resolved": "https://registry.npmmirror.com/filepond-plugin-image-edit/-/filepond-plugin-image-edit-1.6.3.tgz",
-      "integrity": "sha512-5q3RDaVlfvyI346ckF1DfKw4uN5rfAmUCv7HCG30jBZcGmepg8hFyjVM71uZXYeb4AgLhpCkSPP8Immwig8bzw=="
-    },
-    "filepond-plugin-image-exif-orientation": {
-      "version": "1.0.11",
-      "resolved": "https://registry.npmmirror.com/filepond-plugin-image-exif-orientation/-/filepond-plugin-image-exif-orientation-1.0.11.tgz",
-      "integrity": "sha512-hLBc12Fk6Zkj3L8mSAn+elugHOqT5rLUbgVXQQIQjMe0FsGjtpoxqeVR6jt4IWHGat2L9sFAgU2TGmd1mqosCg=="
-    },
-    "filepond-plugin-image-preview": {
-      "version": "4.6.11",
-      "resolved": "https://registry.npmmirror.com/filepond-plugin-image-preview/-/filepond-plugin-image-preview-4.6.11.tgz",
-      "integrity": "sha512-0EmQ9HnOb/X0xc5rLcNRhhmdUbp7oiicRwQrcr90ZfVmPJOOZoX3ZGUEsEPj7luMI55huguhcVozdESxtqnuRw=="
-    },
     "filesize": {
       "version": "3.6.1",
       "resolved": "https://registry.npm.taobao.org/filesize/download/filesize-3.6.1.tgz?cache=0&sync_timestamp=1582340747604&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffilesize%2Fdownload%2Ffilesize-3.6.1.tgz",
@@ -15072,11 +15042,6 @@
         }
       }
     },
-    "vue-filepond": {
-      "version": "6.0.3",
-      "resolved": "https://registry.npmmirror.com/vue-filepond/-/vue-filepond-6.0.3.tgz",
-      "integrity": "sha512-m0wArAdpgzOOs19bWA6zzYlHAb2aK+igPoKPZGrzpgKiiELPKW7XZ2OBDXzk7rhpFLkedujVrMqwjPyZfmQTTQ=="
-    },
     "vue-hot-reload-api": {
       "version": "2.3.4",
       "resolved": "https://registry.npm.taobao.org/vue-hot-reload-api/download/vue-hot-reload-api-2.3.4.tgz",

+ 0 - 7
package.json

@@ -17,12 +17,6 @@
     "dashjs": "^4.2.0",
     "dplayer": "^1.26.0",
     "element-ui": "^2.13.0",
-    "filepond": "^4.20.1",
-    "filepond-plugin-file-validate-size": "^2.2.1",
-    "filepond-plugin-file-validate-type": "^1.2.5",
-    "filepond-plugin-image-edit": "^1.6.1",
-    "filepond-plugin-image-exif-orientation": "^1.0.9",
-    "filepond-plugin-image-preview": "^4.6.4",
     "flv.js": "^1.6.2",
     "hls.js": "^1.1.2",
     "js-cookie": "2.2.0",
@@ -40,7 +34,6 @@
     "vue-baidu-map": "^0.21.22",
     "vue-clipboard2": "^0.3.3",
     "vue-cookies": "^1.7.0",
-    "vue-filepond": "^6.0.3",
     "vue-jstree": "^2.1.6",
     "vue-quill-editor": "^3.0.6",
     "vue-router": "^3.4.5",

+ 0 - 113
src/components/card/PostCard.vue

@@ -1,113 +0,0 @@
-<template>
-  <div>
-    <el-row>
-      <el-col :md="4">
-        <el-menu
-          default-active="1"
-          class="el-menu-vertical-demo"
-        >
-          <el-menu-item index="1">
-            <i class="el-icon-upload" />
-            <span slot="title">投稿</span>
-          </el-menu-item>
-          <el-menu-item index="2">
-            <i class="el-icon-files" />
-            <span slot="title">稿件</span>
-          </el-menu-item>
-          <el-menu-item index="3">
-            <i class="el-icon-data-analysis" />
-            <span slot="title">数据</span>
-          </el-menu-item>
-        </el-menu>
-      </el-col>
-      <el-col :md="20">
-        <el-tabs v-model="activeName" @tab-click="handleClick">
-          <el-tab-pane label="视频" name="first">
-            <publish-video v-if="activeName === 'first'" />
-          </el-tab-pane>
-          <el-tab-pane label="音频" name="second">
-            <publish-audio v-if="activeName === 'second'" />
-          </el-tab-pane>
-          <el-tab-pane label="图片" name="third">
-            <publish-image v-if="activeName === 'third'" />
-          </el-tab-pane>
-          <el-tab-pane label="文章" name="fourth">
-            <publish-article v-if="activeName === 'fourth'" />
-          </el-tab-pane>
-        </el-tabs>
-      </el-col>
-    </el-row>
-  </div>
-</template>
-
-<script>
-import PublishVideo from '@/components/upload/PublishVideo'
-import PublishAudio from '@/components/upload/PublishAudio'
-import PublishImage from '@/components/upload/PublishImage'
-import PublishArticle from '@/components/upload/PublishArticle'
-
-export default {
-  name: 'Publish',
-  components: { PublishVideo, PublishAudio, PublishImage, PublishArticle },
-  data() {
-    return {
-      activeName: 'first',
-      coverUrl: null,
-      videoUrlId: null,
-      coverFile: null,
-      dialogImageUrl: '',
-      dialogVisible: false,
-      disabled: false,
-      imageList: [],
-      imageUrl: ''
-    }
-  },
-  created() {
-  },
-  methods: {
-  }
-}
-</script>
-
-<style>
-.uploader-example {
-  width: 500px;
-  padding: 15px;
-  margin: 40px auto 0;
-  font-size: 12px;
-  box-shadow: 0 0 10px rgba(0, 0, 0, .4);
-}
-.uploader-example .uploader-btn {
-  margin-right: 4px;
-}
-.uploader-example .uploader-list {
-  max-height: 440px;
-  overflow: auto;
-  overflow-x: hidden;
-  overflow-y: auto;
-}
-
-.avatar-uploader .el-upload {
-  border: 1px dashed #d9d9d9;
-  border-radius: 6px;
-  cursor: pointer;
-  position: relative;
-  overflow: hidden;
-}
-.avatar-uploader .el-upload:hover {
-  border-color: #409EFF;
-}
-.avatar-uploader-icon {
-  font-size: 28px;
-  color: #8c939d;
-  width: 320px;
-  height: 240px;
-  line-height: 178px;
-  text-align: center;
-}
-.avatar {
-  width: 320px;
-  height: 240px;
-  display: block;
-}
-</style>

+ 6 - 6
src/components/upload/EditArticle.vue

@@ -32,7 +32,7 @@
             <el-button style="float: right; padding: 3px 0" type="text" @click="onUpdateArticleContent">更新</el-button>
           </div>
           <div>
-            <rich-text :text="form.content" @content=processContent style="width: 80%; padding-right: 2px" />
+            <rich-text :text="form.content" style="width: 80%; padding-right: 2px" @content="processContent" />
           </div>
         </el-card>
       </el-col>
@@ -43,7 +43,7 @@
 <script>
 import RichText from '@/components/RichText'
 
-import {getArticlePost, updateArticleContent,} from '@/api/article'
+import { getArticlePost, updateArticleContent } from '@/api/article'
 
 export default {
   name: 'EditArticle',
@@ -52,12 +52,12 @@ export default {
     return {
       titleForm: {
         articleId: null,
-        title: null,
+        title: null
       },
       form: {
         articleId: null,
-        content: null,
-      },
+        content: null
+      }
     }
   },
   created() {
@@ -106,7 +106,7 @@ export default {
         type: 'warning',
         duration: 3000
       })
-    },
+    }
   }
 }
 </script>

+ 4 - 4
src/components/upload/EditAudio.vue

@@ -33,7 +33,7 @@
 </template>
 
 <script>
-import {getAudioPost,} from '@/api/audio'
+import { getAudioPost } from '@/api/audio'
 
 export default {
   name: 'EditAudio',
@@ -41,8 +41,8 @@ export default {
     return {
       form: {
         title: null,
-        description: null,
-      },
+        description: null
+      }
     }
   },
   created() {
@@ -68,7 +68,7 @@ export default {
         type: 'info',
         duration: 3000
       })
-    },
+    }
   }
 }
 </script>

+ 5 - 5
src/components/upload/EditVideo.vue

@@ -100,7 +100,7 @@ export default {
   name: 'EditVideo',
   data() {
     return {
-      /***********************************************************************/
+      // ****************************************************************************************************************
       options: {
         target: '//oss.reghao.cn/',
         chunkSize: 1024 * 1024 * 1024 * 5, // 5GiB
@@ -125,7 +125,7 @@ export default {
       imgData: {
         channelId: 5
       },
-      /***********************************************************************/
+      // ****************************************************************************************************************
       coverUrl: null,
       coverUrl1: null,
       coverFileId: null,
@@ -214,7 +214,7 @@ export default {
     })
   },
   methods: {
-    /***********************************************************************/
+    // ****************************************************************************************************************
     onFileAdded(file) {
       if (file.file.size > 1024*1024*1024*5) {
         file.cancel()
@@ -257,7 +257,7 @@ export default {
         }
       )
     },
-    /***********************************************************************/
+    // ****************************************************************************************************************
     beforeAvatarUpload(file) {
       const isJPG = file.type === 'image/jpeg'
       const isLt2M = file.size / 1024 / 1024 < 2
@@ -287,7 +287,7 @@ export default {
     },
     handleOnChange(file, fileList) {
     },
-    /***********************************************************************/
+    // ****************************************************************************************************************
     onReturnVideo() {
       this.$router.push('/post/video')
     },

+ 0 - 103
src/components/upload/FilepodImage.vue

@@ -1,103 +0,0 @@
-<template>
-  <div>
-    <file-pond
-      ref="pond"
-      name="file"
-      label-idle="选择图片或拖动图片到此处"
-      label-file-processing="图片正在上传,请稍后"
-      label-file-processing-aborted="图片上传被取消"
-      label-tap-to-retry="尝试重试"
-      label-file-processing-complete="图片上传成功!"
-      label-max-file-size="上传的图片大小不能超过 10MB"
-      label-max-file-size-exceeded="上传的图片大小不能超过 10MB"
-      allow-file-size-validation="true"
-      max-file-size="10MB"
-      accepted-file-types="image/png, image/jpeg, image/jpg, image/gif"
-      :allow-multiple="true"
-      :max-files="12"
-      :server="server"
-      :instant-upload="true"
-      @init="handleFilePondInit"
-      @processfile="success"
-      @removefile="removeFile"
-    />
-  </div>
-</template>
-
-<script>
-import VueFilePond from 'vue-filepond'
-import 'filepond/dist/filepond.min.css'
-import FilePondPluginImagePreview from 'filepond-plugin-image-preview'
-import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.min.css'
-import FilePondPluginFileValidateType from 'filepond-plugin-file-validate-type'
-import FilePondPluginFileValidateSize from 'filepond-plugin-file-validate-size'
-
-// Create component
-const FilePond = VueFilePond(
-  FilePondPluginFileValidateType,
-  FilePondPluginImagePreview,
-  FilePondPluginFileValidateSize
-)
-var resp = ''
-
-export default {
-  name: 'FilePondImage',
-  components: {
-    FilePond
-  },
-  resp,
-  data() {
-    return {
-      imgMap: {},
-      server: {
-        url: '//oss.reghao.cn/',
-        revert: null,
-        process: {
-          headers: {
-            'Authorization': this.$store.getters.token
-          },
-          ondata(formData) {
-            return formData
-          },
-          onload(response) {
-            resp = JSON.parse(response)
-          }
-        }
-      }
-    }
-  },
-  created() {
-  },
-  methods: {
-    handleFilePondInit() {
-      // FilePond instance methods are available on `this.$refs.pond`
-    },
-    success(error, metadata) {
-      if (error === null) {
-        const file = metadata.file
-        const filename = file.name
-        this.imgMap[filename] = resp.data.uploadId
-      }
-      this.$emit('resp', resp)
-    },
-    removeFile(error, metadata) {
-      if (error === null) {
-        const file = metadata.file
-        const uploadId = this.imgMap[file.name]
-        fetch('//file.reghao.cn/api/file/rm/' + uploadId, {
-          headers: {
-            'Authorization': this.$store.getters.token
-          },
-          method: 'DELETE'
-        }).then(response => response.json())
-          .then(json => {
-            console.log(json)
-          })
-          .catch(e => {
-            return null
-          })
-      }
-    }
-  }
-}
-</script>

+ 2 - 2
src/components/upload/PublishArticle.vue

@@ -10,7 +10,7 @@
           <el-input v-model="form.excerpt" type="textarea" autosize style="padding-right: 1px;" />
         </el-form-item>
         <el-form-item label="内容">
-          <rich-text @content=processContent style="width: 80%; padding-right: 2px" />
+          <rich-text style="width: 80%; padding-right: 2px" @content="processContent" />
           <!-- <mavon-editor v-model="content" style="width: 90%; padding-right: 2px" />-->
         </el-form-item>
         <el-form-item>
@@ -23,7 +23,7 @@
 
 <script>
 import RichText from '@/components/RichText'
-import { submitArticle } from "@/api/article";
+import { submitArticle } from '@/api/article'
 
 export default {
   name: 'PublishArticle',

+ 20 - 20
src/components/upload/PublishAudio.vue

@@ -52,8 +52,8 @@
                 <el-date-picker
                   v-model="form.scheduledPubDate"
                   type="datetime"
-                  placeholder="选择定时发布的时间">
-                </el-date-picker>
+                  placeholder="选择定时发布的时间"
+                />
               </el-form-item>
             </el-form>
           </div>
@@ -65,13 +65,13 @@
 
 <script>
 import { getServerInfo } from '@/api/content'
-import { addAudioPost } from "@/api/audio";
+import { addAudioPost } from '@/api/audio'
 
 export default {
   name: 'PublishAudio',
   data() {
     return {
-      /***********************************************************************/
+      // ****************************************************************************************************************
       options: {
         target: '//oss.reghao.cn/',
         chunkSize: 1024 * 1024 * 1024, // 1GiB
@@ -89,15 +89,15 @@ export default {
       attrs: {
         accept: 'audio/*'
       },
-      /***********************************************************************/
+      // ****************************************************************************************************************
       form: {
         audioFileId: null,
         audioUrl: null,
         title: null,
         description: null,
-        scope: "1",
+        scope: '1',
         scheduledPubDate: null
-      },
+      }
     }
   },
   created() {
@@ -106,7 +106,7 @@ export default {
         const resData = res.data
         this.options.target = resData.ossUrl
         this.options.chunkSize = resData.maxSize
-        this.options.headers.Authorization = "Bearer " + resData.token
+        this.options.headers.Authorization = 'Bearer ' + resData.token
       } else {
         this.$notify({
           title: '提示',
@@ -125,7 +125,7 @@ export default {
     })
   },
   methods: {
-    /***********************************************************************/
+    // ****************************************************************************************************************
     onFileAdded(file) {
       this.setTitle(file.file.name)
     },
@@ -148,7 +148,7 @@ export default {
     onFileError(rootFile, file, response, chunk) {
       console.log('文件上传错误')
     },
-    /***********************************************************************/
+    // ****************************************************************************************************************
     setTitle(title) {
       if (title.length > 50) {
         this.form.title = title.substring(0, 50)
@@ -160,22 +160,22 @@ export default {
     onSubmit() {
       if (!this.form.audioFileId) {
         this.$notify({
-            title: '提示',
-            message: '你还没有上传音频',
-            type: 'warning',
-            duration: 3000
-          }
+          title: '提示',
+          message: '你还没有上传音频',
+          type: 'warning',
+          duration: 3000
+        }
         )
         return
       }
 
       if (this.form.title === null) {
         this.$notify({
-            title: '提示',
-            message: '稿件标题不能为空',
-            type: 'warning',
-            duration: 3000
-          }
+          title: '提示',
+          message: '稿件标题不能为空',
+          type: 'warning',
+          duration: 3000
+        }
         )
         return
       }

+ 288 - 0
src/components/upload/PublishFile.vue

@@ -0,0 +1,288 @@
+<template>
+  <el-row class="movie-list">
+    <el-col :md="12" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
+      <el-row style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
+        <el-card class="box-card">
+          <div slot="header" class="clearfix">
+            <span>上传视频文件</span>
+          </div>
+          <div class="text item">
+            <uploader
+              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-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">
+            <span>上传用户头像</span>
+          </div>
+          <div class="text item">
+            <el-tooltip class="item" effect="dark" content="点击上传图片" placement="top-end">
+              <el-upload
+                class="avatar-uploader"
+                action="//oss.reghao.cn/"
+                :headers="imgHeaders"
+                :data="imgData"
+                :with-credentials="true"
+                :show-file-list="false"
+                :before-upload="beforeAvatarUpload"
+                :on-success="handleAvatarSuccess"
+                :on-change="handleOnChange"
+              >
+                <img v-if="coverUrl" :src="coverUrl" class="avatar">
+                <i v-else class="el-icon-plus avatar-uploader-icon" />
+              </el-upload>
+            </el-tooltip>
+          </div>
+        </el-card>
+      </el-row>
+    </el-col>
+    <el-col :md="12" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
+      <el-row style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
+        <el-card class="box-card">
+          <div slot="header" class="clearfix">
+            <span>文件地址</span>
+          </div>
+          <div class="text item">
+            <el-form ref="form" :model="form" label-width="80px">
+              <el-form-item label="文件地址">
+                <el-input v-model="form.fileUrl" style="padding-right: 1px" readonly />
+              </el-form-item>
+              <el-form-item label="头像地址">
+                <el-input v-model="form.imageUrl" style="padding-right: 1px" readonly />
+              </el-form-item>
+            </el-form>
+          </div>
+        </el-card>
+      </el-row>
+    </el-col>
+  </el-row>
+</template>
+
+<script>
+import { getServerInfo } from '@/api/content'
+
+export default {
+  name: 'PublishFile',
+  data() {
+    return {
+      // ****************************************************************************************************************
+      options: {
+        target: '//oss.reghao.cn/',
+        chunkSize: 1024 * 1024 * 1024 * 10, // 10GiB
+        fileParameterName: 'file',
+        testChunks: false,
+        query: (file, chunk) => {
+          return {
+            channelId: 2
+          }
+        },
+        headers: {
+          Authorization: ''
+        },
+        withCredentials: true
+      },
+      attrs: {
+        accept: 'video/*'
+      },
+      // ****************************************************************************************************************
+      imgOssUrl: null,
+      imgHeaders: {
+        Authorization: ''
+      },
+      imgData: {
+        channelId: 4
+      },
+      coverUrl: null,
+      // ****************************************************************************************************************
+      form: {
+        fileUrl: null,
+        imageUrl: null
+      }
+    }
+  },
+  created() {
+    getServerInfo(2).then(res => {
+      if (res.code === 0) {
+        const resData = res.data
+        this.options.target = resData.ossUrl
+        this.options.chunkSize = resData.maxSize
+        this.options.headers.Authorization = 'Bearer ' + resData.token
+      } else {
+        this.$notify({
+          title: '提示',
+          message: '获取 OSS 服务器地址失败, 暂时无法上传文件',
+          type: 'error',
+          duration: 3000
+        })
+      }
+    }).catch(error => {
+      this.$notify({
+        title: '提示',
+        message: error.message,
+        type: 'warning',
+        duration: 3000
+      })
+    })
+
+    getServerInfo(4).then(res => {
+      if (res.code === 0) {
+        const resData = res.data
+        this.imgOssUrl = resData.ossUrl
+        this.imgHeaders.Authorization = 'Bearer ' + resData.token
+      } else {
+        this.$notify({
+          title: '提示',
+          message: '获取 OSS 服务器地址失败, 暂时无法上传文件',
+          type: 'error',
+          duration: 3000
+        })
+      }
+    }).catch(error => {
+      this.$notify({
+        title: '提示',
+        message: error.message,
+        type: 'warning',
+        duration: 3000
+      })
+    })
+    this.getVideoCategory()
+  },
+  mounted() {
+  },
+  methods: {
+    // ****************************************************************************************************************
+    onFileAdded(file) {
+      if (file.file.size > 1024 * 1024 * 1024 * 5) {
+        file.cancel()
+        this.$notify({
+          title: '提示',
+          message: '视频文件应小于 5GiB',
+          type: 'warning',
+          duration: 3000
+        })
+        return
+      }
+    },
+    onFileProgress(rootFile, file, chunk) {
+    },
+    onFileSuccess(rootFile, file, response, chunk) {
+      const res = JSON.parse(response)
+      if (res.code === 0) {
+        const resData = res.data
+        this.form.fileUrl = resData.uploadId
+        this.$notify({
+          title: '提示',
+          message: '视频已上传',
+          type: 'warning',
+          duration: 3000
+        })
+      } else {
+        this.$notify({
+          title: '提示',
+          message: '视频文件上传失败',
+          type: 'warning',
+          duration: 3000
+        })
+      }
+    },
+    onFileError(rootFile, file, response, chunk) {
+      const res = JSON.parse(response)
+      console.log(res.msg)
+      this.$notify({
+        title: '提示',
+        message: '视频文件上传错误',
+        type: 'warning',
+        duration: 3000
+      })
+    },
+    // ****************************************************************************************************************
+    beforeAvatarUpload(file) {
+      const isJPG = file.type === 'image/jpeg'
+      const isLt2M = file.size / 1024 / 1024 < 10
+      if (!isJPG) {
+        this.$message.error('封面图片只能是 JPG 格式!')
+      }
+      if (!isLt2M) {
+        this.$message.error('封面图片大小不能超过 10MB!')
+      }
+      return isJPG && isLt2M
+    },
+    handleAvatarSuccess(res, file) {
+      if (res.code === 0) {
+        const resData = res.data
+        this.coverUrl = URL.createObjectURL(file.raw)
+        this.form.imageUrl = resData.url
+      } else {
+        this.$notify({
+          title: '提示',
+          message: '视频封面上传失败,请重试!' + res.msg,
+          type: 'warning',
+          duration: 3000
+        })
+      }
+    },
+    handleOnChange(file, fileList) {
+    }
+    // ****************************************************************************************************************
+  }
+}
+</script>
+
+<style>
+.uploader-example {
+  width: 500px;
+  padding: 15px;
+  margin: 40px auto 0;
+  font-size: 12px;
+  box-shadow: 0 0 10px rgba(0, 0, 0, .4);
+}
+.uploader-example .uploader-btn {
+  margin-right: 4px;
+}
+.uploader-example .uploader-list {
+  max-height: 440px;
+  overflow: auto;
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+
+.avatar-uploader .el-upload {
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+}
+.avatar-uploader .el-upload:hover {
+  border-color: #409EFF;
+}
+.avatar-uploader-icon {
+  font-size: 28px;
+  color: #8c939d;
+  width: 320px;
+  height: 240px;
+  line-height: 178px;
+  text-align: center;
+}
+.avatar {
+  width: 320px;
+  height: 240px;
+  display: block;
+}
+</style>

+ 13 - 13
src/components/upload/PublishImage.vue

@@ -21,7 +21,7 @@
             :on-remove="handleOnRemove"
             :on-preview="handleOnPreview"
           >
-            <i class="el-icon-plus"></i>
+            <i class="el-icon-plus" />
           </el-upload>
           <el-dialog :visible.sync="dialogVisible">
             <img width="100%" :src="dialogImageUrl" alt="">
@@ -52,8 +52,8 @@
               <el-date-picker
                 v-model="submitForm.scheduledPubDate"
                 type="datetime"
-                placeholder="选择定时发布的时间">
-              </el-date-picker>
+                placeholder="选择定时发布的时间"
+              />
             </el-form-item>
           </el-form>
         </div>
@@ -72,7 +72,7 @@ export default {
   components: {},
   data() {
     return {
-      /***********************************************************************/
+      // ****************************************************************************************************************
       imgHeaders: {
         Authorization: ''
       },
@@ -82,11 +82,11 @@ export default {
       dialogImageUrl: '',
       dialogVisible: false,
       uploadImages: [],
-      /***********************************************************************/
+      // ****************************************************************************************************************
       submitForm: {
         imageFileIds: [],
         albumName: null,
-        scope: "1",
+        scope: '1',
         scheduledPubDate: null
       },
       submitFormRules: {
@@ -100,7 +100,7 @@ export default {
     getServerInfo(this.imgData.channelId).then(res => {
       if (res.code === 0) {
         const resData = res.data
-        this.imgHeaders.Authorization = "Bearer " + resData.token
+        this.imgHeaders.Authorization = 'Bearer ' + resData.token
       } else {
         this.$notify({
           title: '失败提示',
@@ -119,12 +119,12 @@ export default {
     })
   },
   methods: {
-    /***********************************************************************/
+    // ****************************************************************************************************************
     handleBeforeUpload(file) {
       const fileType = file.type
       var isJPG = false
-      if (file.type === 'image/jpeg' || file.type === 'image/webp'
-        || file.type === 'image/gif' || file.type === 'image/png') {
+      if (file.type === 'image/jpeg' || file.type === 'image/webp' ||
+        file.type === 'image/gif' || file.type === 'image/png') {
         isJPG = true
       }
 
@@ -163,10 +163,10 @@ export default {
       imageFileMap.delete(file.name)
     },
     handleOnPreview(file) {
-      this.dialogImageUrl = file.url;
-      this.dialogVisible = true;
+      this.dialogImageUrl = file.url
+      this.dialogVisible = true
     },
-    /***********************************************************************/
+    // ****************************************************************************************************************
     onSubmit(formName) {
       this.$refs[formName].validate(valid => {
         if (!valid) return false

+ 104 - 102
src/components/upload/PublishVideo.vue

@@ -70,20 +70,24 @@
               <el-form-item label="分区">
                 <el-select v-model="form.categoryPid" placeholder="请选择分区" @change="getCategory">
                   <el-option
-                    v-for="item in pCategoryList" :key="item.value"
-                    :label="item.label" :value="item.value">
-                  </el-option>
+                    v-for="item in pCategoryList"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"
+                  />
                 </el-select>
                 <el-select v-model="form.categoryId" placeholder="请选择子分区">
                   <el-option
-                    v-for="item in categoryList" :key="item.value"
-                    :label="item.label" :value="item.value">
-                  </el-option>
+                    v-for="item in categoryList"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"
+                  />
                 </el-select>
               </el-form-item>
               <el-form-item label="标签">
-                <el-select v-model="form.tags" style="padding-right: 1px" placeholder="输入标签,用回车添加" @change="getRecommendTags" clearable multiple filterable allow-create default-first-option>
-                  <el-option v-for="item in rcmdTags" :key="item.value" :label="item.label" :value="item.label"></el-option>
+                <el-select v-model="form.tags" style="padding-right: 1px" placeholder="输入标签,用回车添加" clearable multiple filterable allow-create default-first-option @change="getRecommendTags">
+                  <el-option v-for="item in rcmdTags" :key="item.value" :label="item.label" :value="item.label" />
                 </el-select>
               </el-form-item>
               <el-form-item label="可见范围">
@@ -98,8 +102,8 @@
                 <el-date-picker
                   v-model="form.scheduledPubDate"
                   type="datetime"
-                  placeholder="选择定时发布的时间">
-                </el-date-picker>
+                  placeholder="选择定时发布的时间"
+                />
               </el-form-item>
             </el-form>
           </div>
@@ -111,13 +115,13 @@
 
 <script>
 import { getServerInfo } from '@/api/content'
-import {videoCategory, addVideoPost } from '@/api/video'
+import { videoCategory, addVideoPost } from '@/api/video'
 
 export default {
   name: 'PublishVideo',
   data() {
     return {
-      /***********************************************************************/
+      // ****************************************************************************************************************
       options: {
         target: '//oss.reghao.cn/',
         chunkSize: 1024 * 1024 * 1024 * 10, // 10GiB
@@ -131,12 +135,12 @@ export default {
         headers: {
           Authorization: ''
         },
-        withCredentials: true,
+        withCredentials: true
       },
       attrs: {
         accept: 'video/*'
       },
-      /***********************************************************************/
+      // ****************************************************************************************************************
       imgOssUrl: null,
       imgHeaders: {
         Authorization: ''
@@ -145,7 +149,7 @@ export default {
         channelId: 5
       },
       coverUrl: null,
-      /***********************************************************************/
+      // ****************************************************************************************************************
       categoryMap: {
         Set: function(key, value) { this[key] = value },
         Get: function(key) { return this[key] },
@@ -155,7 +159,7 @@ export default {
       pCategoryList: [],
       categoryList: [],
       rcmdTags: [
-        /*{ label: "知识点1" }*/
+        /* { label: "知识点1" }*/
       ],
       form: {
         videoFileId: null,
@@ -165,9 +169,9 @@ export default {
         categoryPid: null,
         categoryId: null,
         tags: [],
-        scope: "1",
+        scope: '1',
         scheduledPubDate: null
-      },
+      }
     }
   },
   created() {
@@ -176,7 +180,7 @@ export default {
         const resData = res.data
         this.options.target = resData.ossUrl
         this.options.chunkSize = resData.maxSize
-        this.options.headers.Authorization = "Bearer " + resData.token
+        this.options.headers.Authorization = 'Bearer ' + resData.token
       } else {
         this.$notify({
           title: '提示',
@@ -198,7 +202,7 @@ export default {
       if (res.code === 0) {
         const resData = res.data
         this.imgOssUrl = resData.ossUrl
-        this.imgHeaders.Authorization = "Bearer " + resData.token
+        this.imgHeaders.Authorization = 'Bearer ' + resData.token
       } else {
         this.$notify({
           title: '提示',
@@ -220,16 +224,16 @@ export default {
   mounted() {
   },
   methods: {
-    /***********************************************************************/
+    // ****************************************************************************************************************
     onFileAdded(file) {
-      if (file.file.size > 1024*1024*1024*5) {
+      if (file.file.size > 1024 * 1024 * 1024 * 5) {
         file.cancel()
         this.$notify({
-            title: '提示',
-            message: '视频文件应小于 5GiB',
-            type: 'warning',
-            duration: 3000
-          })
+          title: '提示',
+          message: '视频文件应小于 5GiB',
+          type: 'warning',
+          duration: 3000
+        })
         return
       }
       this.setTitle(file.file.name)
@@ -249,7 +253,6 @@ export default {
           duration: 3000
         })
       } else {
-        console.log(chunk)
         this.$notify({
           title: '提示',
           message: '视频文件上传失败',
@@ -262,13 +265,13 @@ export default {
       const res = JSON.parse(response)
       console.log(res.msg)
       this.$notify({
-          title: '提示',
-          message: '视频文件上传错误',
-          type: 'warning',
-          duration: 3000
-        })
+        title: '提示',
+        message: '视频文件上传错误',
+        type: 'warning',
+        duration: 3000
+      })
     },
-    /***********************************************************************/
+    // ****************************************************************************************************************
     // 选择视频后获取视频的分辨率和时长, 并截取第一秒的内容作为封面
     processVideo(file) {
       return new Promise((resolve, reject) => {
@@ -329,7 +332,7 @@ export default {
               type: 'warning',
               duration: 3000
             })
-            return;
+            return
           }
 
           const formData = new FormData()
@@ -341,27 +344,27 @@ export default {
             credentials: 'include',
             body: formData
           }).then(response => response.json()).then(json => {
-              if (json.code === 0) {
-                this.coverUrl = URL.createObjectURL(coverFile)
-                const resData = json.data
-                this.form.coverFileId = resData.uploadId
-              } else {
-                this.$notify({
-                  title: '提示',
-                  message: '视频封面上传失败,请重试!' + json.msg,
-                  type: 'warning',
-                  duration: 3000
-                })
-              }
-            }).catch(e => {
-              return null
-            })
+            if (json.code === 0) {
+              this.coverUrl = URL.createObjectURL(coverFile)
+              const resData = json.data
+              this.form.coverFileId = resData.uploadId
+            } else {
+              this.$notify({
+                title: '提示',
+                message: '视频封面上传失败,请重试!' + json.msg,
+                type: 'warning',
+                duration: 3000
+              })
+            }
+          }).catch(e => {
+            return null
+          })
         }
       }, 1000) // 1000毫秒,就是截取第一秒,2000毫秒就是截取第2秒,视频1秒通常24帧,也可以换算成截取第几帧。
       // 防止拖动进度条的时候重复触发
       // videoElem.removeEventListener('canplay', arguments.callee)
     },
-    /***********************************************************************/
+    // ****************************************************************************************************************
     beforeAvatarUpload(file) {
       const isJPG = file.type === 'image/jpeg'
       const isLt2M = file.size / 1024 / 1024 < 10
@@ -376,7 +379,7 @@ export default {
     handleAvatarSuccess(res, file) {
       if (res.code === 0) {
         const resData = res.data
-        this.coverUrl = URL.createObjectURL(file.raw);
+        this.coverUrl = URL.createObjectURL(file.raw)
         this.form.coverFileId = resData.uploadId
       } else {
         this.$notify({
@@ -388,9 +391,8 @@ export default {
       }
     },
     handleOnChange(file, fileList) {
-      console.log('封面改变')
     },
-    /***********************************************************************/
+    // ****************************************************************************************************************
     setTitle(title) {
       if (title.length > 50) {
         this.form.title = title.substring(0, 50)
@@ -401,36 +403,36 @@ export default {
     },
     getVideoCategory() {
       videoCategory().then(res => {
-          if (res.code === 0) {
-            const resData = res.data
-            for (let i = 0; i < resData.length; i++) {
-              const name = resData[i].name
-              const id = resData[i].id
-              this.pCategoryList.push({label: name, value: id})
-              this.categoryMap.Set(id, resData[i].children)
-            }
-          } else {
-            this.$notify({
-              title: '提示',
-              message: res.msg,
-              type: 'warning',
-              duration: 3000
-            })
+        if (res.code === 0) {
+          const resData = res.data
+          for (let i = 0; i < resData.length; i++) {
+            const name = resData[i].name
+            const id = resData[i].id
+            this.pCategoryList.push({ label: name, value: id })
+            this.categoryMap.Set(id, resData[i].children)
           }
-        }).catch(error => {
+        } else {
           this.$notify({
             title: '提示',
-            message: error.message,
-            type: 'error',
+            message: res.msg,
+            type: 'warning',
             duration: 3000
           })
+        }
+      }).catch(error => {
+        this.$notify({
+          title: '提示',
+          message: error.message,
+          type: 'error',
+          duration: 3000
         })
+      })
     },
     getCategory(id) {
       // 重置子分区,清除前一次选择分区时留下的缓存
       this.categoryList = []
       for (const item of this.categoryMap.Get(id)) {
-        this.categoryList.push({label: item.name, value: item.id})
+        this.categoryList.push({ label: item.name, value: item.id })
       }
     },
     // 根据输入的标签获取相似的标签
@@ -442,44 +444,44 @@ export default {
     onSubmit() {
       if (!this.form.videoFileId) {
         this.$notify({
-            title: '提示',
-            message: '你还没有上传视频',
-            type: 'warning',
-            duration: 3000
-          }
+          title: '提示',
+          message: '你还没有上传视频',
+          type: 'warning',
+          duration: 3000
+        }
         )
         return
       }
 
       if (!this.form.coverFileId) {
         this.$notify({
-            title: '提示',
-            message: '你还没有上传视频封面',
-            type: 'warning',
-            duration: 3000
-          }
+          title: '提示',
+          message: '你还没有上传视频封面',
+          type: 'warning',
+          duration: 3000
+        }
         )
         return
       }
 
       if (this.form.title === '' || this.form.categoryId === -1) {
         this.$notify({
-            title: '提示',
-            message: '分区和稿件标题不能为空',
-            type: 'warning',
-            duration: 3000
-          }
+          title: '提示',
+          message: '分区和稿件标题不能为空',
+          type: 'warning',
+          duration: 3000
+        }
         )
         return
       }
 
       if (this.form.tags.length === 0 || this.form.tags.length > 10) {
         this.$notify({
-            title: '提示',
-            message: '标签最少 1 个, 最多 10 个',
-            type: 'warning',
-            duration: 3000
-          }
+          title: '提示',
+          message: '标签最少 1 个, 最多 10 个',
+          type: 'warning',
+          duration: 3000
+        }
         )
         return
       }
@@ -506,20 +508,20 @@ export default {
           })
           this.$router.push('/post/video')
         } else {
-          this.$notify({
-              title: '提示',
-              message: res.msg,
-              type: 'warning',
-              duration: 3000
-          })
-        }
-      }).catch(error => {
           this.$notify({
             title: '提示',
-            message: error.message,
+            message: res.msg,
             type: 'warning',
             duration: 3000
           })
+        }
+      }).catch(error => {
+        this.$notify({
+          title: '提示',
+          message: error.message,
+          type: 'warning',
+          duration: 3000
+        })
       })
     }
   }

+ 0 - 260
src/components/upload/UploadFile.vue

@@ -1,260 +0,0 @@
-<template>
-  <el-col>
-    <el-card>
-      <el-row>
-        <h2>上传文件</h2>
-        <uploader
-          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>
-      </el-row>
-      <el-divider />
-      <el-row>
-        <h2>文件信息</h2>
-      </el-row>
-      <el-form ref="form" :model="form" label-width="80px">
-        <el-form-item label="标题">
-          <el-input v-model="form.title" style="width: 70%; padding-right: 2px" placeholder="标题不能超过 50 个字符" />
-        </el-form-item>
-        <el-form-item label="描述">
-          <el-input v-model="form.description" type="textarea" style="width: 70%; padding-right: 2px" />
-        </el-form-item>
-        <el-form-item>
-          <el-button type="primary" @click="onSubmit">立即投稿</el-button>
-          <el-button>取消</el-button>
-        </el-form-item>
-      </el-form>
-    </el-card>
-  </el-col>
-</template>
-
-<script>
-import { hashFile } from '@/utils/hash'
-
-export default {
-  name: 'UploadFile',
-  data() {
-    return {
-      /***********************************************************************/
-      options: {
-        target: '//oss.reghao.cn/?multipart',
-        chunkSize: 1024 * 1024 * 10, // 10MiB
-        //target: '//oss.reghao.cn/',
-        //chunkSize: 1024 * 1024 * 1024 * 5, // 5GiB
-        fileParameterName: 'file',
-        testChunks: true,
-        // 服务器分片校验函数,秒传及断点续传基础
-        checkChunkUploadedByResponse: function (chunk, message) {
-          const resData = JSON.parse(message);
-          let objMessage = resData.data;
-          if (objMessage.skipUpload) {
-            return true;
-          } else {
-            return (objMessage.uploaded || []).indexOf(chunk.offset + 1) >= 0
-          }
-        },
-        query: (file, chunk) => {
-          return {
-            key: this.form.objectName,
-            acl: '',
-            'content-type': '',
-            'success_action_redirect': '',
-            'x-amz-meta-uuid': '',
-            'x-amz-server-side-encryption': '',
-            'X-amz-credential': '',
-            'x-amz-algorithm': '',
-            'x-amz-date': '',
-            'x-amz-meta-tag': '',
-            'x-amz-signature': ''
-          }
-        },
-        headers: {
-        }
-      },
-      attrs: {
-        accept: 'video/*'
-      },
-      /***********************************************************************/
-      form: {
-        title: null,
-        description: null,
-      }
-    }
-  },
-  created() {
-  },
-  methods: {
-    /***********************************************************************/
-    onFileAdded(file) {
-      this.setTitle(file.file.name)
-       file.pause()
-      hashFile(file.file).then(res => {
-        const formData = new FormData()
-        formData.append('filename', file.file.name)
-        formData.append('size', file.file.size)
-        formData.append('sha256sum', res.sha256sum)
-        fetch(`//oss.reghao.cn/?create`, {
-          /*headers: {
-            Authorization: 'Bearer ' + this.$store.getters.token
-          },*/
-          method: 'POST',
-          credentials: 'include',
-          body: formData
-        }).then(response => response.json())
-          .then(json => {
-            const uploadId = json.data.uploadId
-            const exist = json.data.exist
-            if (exist) {
-              this.message = '视频已存在'
-              this.showMessage = true
-              file.cancel()
-            } else {
-              file.uniqueIdentifier = res.sha256sum
-              file.resume()
-            }
-          }).catch(e => {
-            return null
-          })
-      })
-    },
-    onFileProgress(rootFile, file, chunk) {
-    },
-    onFileSuccess(rootFile, file, response, chunk) {
-      const res = JSON.parse(response)
-      if (res.code === 0) {
-        console.log(res)
-        this.$notify(
-          {
-            title: '提示',
-            message: '文件已上传',
-            type: 'warning',
-            duration: 3000
-          }
-        )
-      }
-    },
-    onFileError(rootFile, file, response, chunk) {
-      this.$notify(
-        {
-          title: '提示',
-          message: '文件上传错误',
-          type: 'warning',
-          duration: 3000
-        }
-      )
-    },
-    /***********************************************************************/
-    setTitle(title) {
-      if (title.length > 50) {
-        this.form.title = title.substring(0, 50)
-        this.form.description = title
-      } else {
-        this.form.title = title
-      }
-    },
-    onSubmit() {
-      if (!this.form.objectName) {
-        this.$notify(
-          {
-            title: '提示',
-            message: '你还没有上传视频',
-            type: 'warning',
-            duration: 3000
-          }
-        )
-        return
-      }
-
-      if (!this.form.coverFileId) {
-        this.$notify(
-          {
-            title: '提示',
-            message: '你还没有上传视频封面',
-            type: 'warning',
-            duration: 3000
-          }
-        )
-        return
-      }
-
-      if (this.form.title === '' || this.form.categoryId === -1) {
-        this.$notify(
-          {
-            title: '提示',
-            message: '分区和稿件标题不能为空',
-            type: 'warning',
-            duration: 3000
-          }
-        )
-        return
-      }
-
-       if (this.form.scope === null) {
-        this.$notify(
-          {
-            title: '提示',
-            message: '稿件可见范围不能为空',
-            type: 'warning',
-            duration: 3000
-          }
-        )
-      }
-    }
-  }
-}
-</script>
-
-<style>
-.uploader-example {
-  width: 500px;
-  padding: 15px;
-  margin: 40px auto 0;
-  font-size: 12px;
-  box-shadow: 0 0 10px rgba(0, 0, 0, .4);
-}
-.uploader-example .uploader-btn {
-  margin-right: 4px;
-}
-.uploader-example .uploader-list {
-  max-height: 440px;
-  overflow: auto;
-  overflow-x: hidden;
-  overflow-y: auto;
-}
-
-.avatar-uploader .el-upload {
-  border: 1px dashed #d9d9d9;
-  border-radius: 6px;
-  cursor: pointer;
-  position: relative;
-  overflow: hidden;
-}
-.avatar-uploader .el-upload:hover {
-  border-color: #409EFF;
-}
-.avatar-uploader-icon {
-  font-size: 28px;
-  color: #8c939d;
-  width: 320px;
-  height: 240px;
-  line-height: 178px;
-  text-align: center;
-}
-.avatar {
-  width: 320px;
-  height: 240px;
-  display: block;
-}
-</style>

+ 5 - 0
src/router/index.js

@@ -284,6 +284,11 @@ const routes = [
     name: 'PostPublishArticle',
     component: PostPublishArticle
   },
+  {
+    path: '/post/publish/file',
+    name: 'PostPublish',
+    component: PostPublish
+  },
   {
     path: '/post/edit/article/:articleId',
     name: 'PostEditArticle',

+ 19 - 12
src/views/post/PostPublish.vue

@@ -13,7 +13,7 @@
       </el-menu>
     </el-col>
     <el-col :md="22">
-      <el-tabs v-model="activeName" @tab-click='tabClick'>
+      <el-tabs v-model="activeName" @tab-click="tabClick">
         <el-tab-pane label="视频" name="video">
           <publish-video v-if="activeName === 'video'" />
         </el-tab-pane>
@@ -26,6 +26,9 @@
         <el-tab-pane label="文章" name="article">
           <publish-article v-if="activeName === 'article'" />
         </el-tab-pane>
+        <el-tab-pane label="文件" name="file">
+          <publish-file v-if="activeName === 'file'" />
+        </el-tab-pane>
       </el-tabs>
     </el-col>
   </el-row>
@@ -36,10 +39,11 @@ import PublishVideo from '@/components/upload/PublishVideo'
 import PublishAudio from '@/components/upload/PublishAudio'
 import PublishImage from '@/components/upload/PublishImage'
 import PublishArticle from '@/components/upload/PublishArticle'
+import PublishFile from '@/components/upload/PublishFile'
 
 export default {
-  name: 'Publish',
-  components: { PublishVideo, PublishAudio, PublishImage, PublishArticle },
+  name: 'PostPublish',
+  components: { PublishVideo, PublishAudio, PublishImage, PublishArticle, PublishFile },
   data() {
     return {
       navList: [
@@ -58,27 +62,30 @@ export default {
       imageUrl: ''
     }
   },
+  watch: {
+    $route() {
+      this.$router.go()
+    }
+  },
   created() {
     const path = this.$route.path
-    if (path.endsWith("image")) {
+    if (path.endsWith('image')) {
       this.activeName = 'image'
       document.title = '发布图片'
-    } else if (path.endsWith("audio")) {
+    } else if (path.endsWith('audio')) {
       this.activeName = 'audio'
       document.title = '发布音频'
-    } else if (path.endsWith("article")) {
+    } else if (path.endsWith('article')) {
       this.activeName = 'article'
       document.title = '发布文章'
+    } else if (path.endsWith('file')) {
+      this.activeName = 'file'
+      document.title = '发布文件'
     } else {
       this.activeName = 'video'
       document.title = '发布视频'
     }
   },
-  watch: {
-    $route(){
-      this.$router.go()
-    }
-  },
   methods: {
     tabClick(tab) {
       this.activeName = tab.name
@@ -91,7 +98,7 @@ export default {
         return
       }
       this.$router.push(path)
-    },
+    }
   }
 }
 </script>