Przeglądaj źródła

文件上传未完成

倚楼听风雨 3 lat temu
rodzic
commit
669b2ad2fb

+ 17 - 0
src/api/fileManager.js

@@ -0,0 +1,17 @@
+/*
+ * @Author: 倚楼听风雨 18408246387@163.com
+ * @Date: 2023-01-09 16:01:45
+ * @LastEditors: 倚楼听风雨 18408246387@163.com
+ * @LastEditTime: 2023-02-20 09:49:31
+ * @FilePath: \log-server-web\src\api\rentComputer.js
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+import service from "@/utils/request";
+
+export const getAllTaskSimple = (data) => {
+  return service({
+    url: "/fileManager/getAllTaskSimple",
+    method: "post",
+    data,
+  });
+};

BIN
src/assets/defultThumUrl.png


+ 199 - 0
src/view/fileManager/components/movefile-dialog.vue

@@ -0,0 +1,199 @@
+<!-- 素材管理移动文件功能弹出页面 -->
+<template>
+  <div class="movefile-dialog-wrap">
+    <el-dialog
+      :title="title"
+      :visible.sync="visible"
+      :show="show"
+      custom-class="dialog-width"
+      @close="$emit('update:show', false)"
+    >
+      <el-tree
+        ref="tree"
+        :data="folderListData"
+        :props="defaultProps"
+        :check-strictly="true"
+        show-checkbox
+        node-key="id"
+        @check-change="orgCheckChange"
+      ></el-tree>
+      <div slot="footer" class="dialog-footer">
+        <el-button size="medium" @click="handleClose">{{
+          $t("common.cancel")
+        }}</el-button>
+        <el-button
+          :loading="move_loading"
+          type="primary"
+          size="medium"
+          @click="handleMoveFile"
+          >{{ $t("common.confirm") }}</el-button
+        >
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  filters: {},
+  props: {
+    ids: {
+      // 当前点击需要移动操作的文件id数组集合
+      type: Array,
+      default: function () {
+        return [];
+      },
+    },
+    parentId: {
+      // 当前移动操作文件所属的文件夹id
+      type: Number,
+      default: 0,
+    },
+    show: {
+      type: Boolean,
+      default: false,
+    },
+  },
+  data() {
+    return {
+      move_loading: false,
+      visible: this.show,
+      title: this.$t("material.moveTo"),
+      dialogLoading: false,
+      folderListData: [], // 文件夹列表数据
+      defaultProps: {
+        children: "children",
+        label: "name",
+      },
+      selectOrg: {
+        orgsid: [],
+      },
+    };
+  },
+  computed: {},
+  watch: {
+    show(val, oldVal) {
+      if (val === oldVal) {
+        return;
+      }
+      this.visible = val;
+      this.handleFechtUserFolderList(); // 每次打开对话框,都去重新获取文件夹列表接口
+    },
+    // 如果内部有新值变化,更新外部的visible
+    visible(val, oldVal) {
+      if (val === oldVal) {
+        return;
+      }
+      this.$emit("update:visible", val);
+    },
+    parentId(val, oldVal) {
+      if (val === oldVal) {
+        return;
+      }
+      // 监测父组件那边传过来的上传文件夹id的变化, 如果有改变,就更新options中的目标上传id
+      this.parentId = val;
+    },
+  },
+  created() {},
+  mounted() {},
+  methods: {
+    handleFechtUserFolderList() {
+      // 处理获取文件夹列表
+      this.loading = true;
+      this.urlmethod(this.url.material.selectDir_res, null)
+        .then((res) => {
+          this.folderListData = [];
+          this.folderListData.push(res.data);
+          this.loading = false;
+        })
+        .catch((err) => {
+          console.log("err", err);
+          this.loading = false;
+        });
+    },
+    handleMoveFile() {
+      // 执行移动文件的操作
+      // this.id就是传递过来的需要操作的文件id
+      if (this.selectOrg.orgsid.length === 1) {
+        this.move_loading = true;
+        const para = {
+          data: {
+            ids: this.ids, // 移动文件的id
+            parentId: this.selectOrg.orgsid[0], // 移动到的目标文件夹id
+          },
+        };
+        this.urlmethod(this.url.material.remove_res, para)
+          .then(() => {
+            // 移动文件操作成功
+            this.$message({
+              type: "success",
+              message: this.$t("common.moveSuccess"),
+            });
+            this.move_loading = false;
+            this.visible = false;
+            this.$emit("removeActiveItem", this.id);
+            // 这里调用父组件重新获取数据刷新列表的方法
+            this.$parent.initMaterialPage(this.parentId);
+          })
+          .catch((err) => {
+            this.move_loading = false;
+            console.log("err", err);
+            this.loading = false;
+          });
+      }
+    },
+    // check-change
+    // 节点选中状态发生变化时的回调
+    // 共三个参数,依次为:传递给 data 属性的数组中该节点所对应的对象、节点本身是否被选中、节点的子树中是否有被选中的节点
+    orgCheckChange(data, checked, indeterminate) {
+      // 获取当前选择的id在数组中的索引
+      const indexs = this.selectOrg.orgsid.indexOf(data.id);
+      // 如果不存在数组中,并且数组中已经有一个id并且checked为true的时候,代表不能再次选择。
+      if (indexs < 0 && this.selectOrg.orgsid.length === 1 && checked) {
+        // this.$message({
+        //   message: this.$t('esell.onlyOneSelect'),
+        //   type: 'warning',
+        //   showClose: true
+        // })
+        // 设置已选择的节点为false 很重要
+
+        this.$refs.tree.setCheckedKeys([]);
+        this.$refs.tree.setChecked(data, true);
+        this.selectOrg.orgsid = [];
+        this.selectOrg.orgsid.push(data.id);
+      } else if (this.selectOrg.orgsid.length === 0 && checked) {
+        // 发现数组为空 并且是已选择
+        // 防止数组有值,首先清空,再push
+        this.selectOrg.orgsid = [];
+        this.selectOrg.orgsid.push(data.id);
+      } else if (
+        indexs >= 0 &&
+        this.selectOrg.orgsid.length === 1 &&
+        !checked
+      ) {
+        // 再次直接进行赋值为空操作
+        this.selectOrg.orgsid = [];
+      }
+    },
+    handleClose() {
+      // 点击取消按钮
+      this.visible = false;
+    },
+  },
+};
+</script>
+<style lang="scss">
+.movefile-dialog-wrap {
+  .el-dialog {
+    border-radius: 6px;
+    .el-dialog__header {
+      border-bottom: 1px solid #d0dfe7;
+      border-top-left-radius: 6px;
+      border-top-right-radius: 6px;
+    }
+  }
+  .dialog-width {
+    min-width: 45rem !important;
+  }
+}
+</style>

+ 107 - 0
src/view/fileManager/components/player.vue

@@ -0,0 +1,107 @@
+<template>
+    <div class="video-container-wrap">
+      <div class="player">
+        <video-player
+          ref="videoPlayer"
+          :playsinline="false"
+          :options="playerOptions"
+          class="video-player vjs-custom-skin"
+          @play="onPlayerPlay($event)"
+          @pause="onPlayerPause($event)"
+          @statechanged="playerStateChanged($event)"
+        ></video-player>
+      </div>
+    </div>
+  </template>
+  <script>
+  // 引入样式
+  import { videoPlayer } from 'vue-video-player'
+  import 'video.js/dist/video-js.css'
+  export default {
+    components: {
+      videoPlayer
+    },
+    props: {
+      videoUrl: { type: String, default: '' },
+      state: { type: Boolean, default: false },
+      poster: { type: String, default: '' }
+    },
+    data() {
+      return {
+        playerOptions: {
+          autoplay: false, // 如果true,浏览器准备好时开始回放。
+          muted: false, // 默认情况下将会消除任何音频。
+          loop: false, // 导致视频一结束就重新开始。
+          preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
+          language: 'en',
+          aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
+          fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
+          sources: [
+            {
+              type: 'video/mp4',
+              src: this.videoUrl // 你的m3u8地址(必填)
+            }
+          ],
+          poster: this.poster,
+          // poster: 'https://surmon-china.github.io/vue-quill-editor/static/images/surmon-3.jpg', // 你的封面地址
+          width: document.documentElement.clientWidth,
+          notSupportedMessage: this.$t('material.noPlay') // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
+        }
+      }
+    },
+    computed: {
+      player() {
+        return this.$refs.videoPlayer.player
+      }
+    },
+    watch: {
+      // 更改视频源 videoUrl从弹出框组件传值
+      videoUrl(val, oldVal) {
+        if (val === oldVal) {
+          return
+        }
+        if (val !== '') {
+          this.playerOptions.sources[0].src = val
+        }
+      },
+   
+      // 弹出框关闭后暂停 否则一直在播放 state从弹出框组件传值
+      state(val, oldVal) {
+        if (val === oldVal) {
+          return
+        }
+        this.$refs.videoPlayer.player.pause()
+      },
+      poster(val, oldVal) {
+        // 检测它的变化,来改变视频封面
+        if (val === oldVal) {
+          return
+        }
+        this.playerOptions.poster = val
+      }
+    },
+    methods: {
+      onPlayerPlay(player) {},
+      onPlayerPause(player) {},
+      playerStateChanged(player) {}
+    }
+  }
+  </script>
+  <style lang="scss">
+  .video-container-wrap {
+    .player {
+      .video-js .vjs-big-play-button {
+        /*
+        播放按钮换成圆形
+       */
+        height: 2em;
+        width: 2em;
+        line-height: 2em;
+        border-radius: 1em;
+        top: 50%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+      }
+    }
+  }
+  </style>

+ 334 - 0
src/view/fileManager/components/uploader-dialog.vue

@@ -0,0 +1,334 @@
+<!-- 素材管理上传功能弹出页面 -->
+<template>
+    <div class="uploader-dialog-wrap">
+      <el-dialog
+   
+        :title="title"
+        :visible.sync="visible"
+        :show="show"
+        :show-close="false"
+        :close-on-click-modal="false"
+        custom-class="dialog-width"
+        @close="$emit('update:show', false)"
+      >
+        <uploader 
+          v-if="visible"
+          ref="uploader"
+          :options="options"
+          :file-status-text="fileStatusText"
+          :auto-start="true"
+          class="uploader-example"
+          @file-added="onFileAdded"
+          @file-progress="onFileProgress"
+          @file-success="onFileSuccess"
+          @file-error="onFileError"
+        >
+          <uploader-unsupport></uploader-unsupport>
+          <uploader-btn ref="uploadBtn" :attrs="attrs" class="global-uploader-btn">{{ $t('material.selectFile') }}</uploader-btn>
+          <uploader-list></uploader-list>
+          <div class="warning-message"><i class="el-icon-warning" style="color:#E6A23C;font-size:20px;"></i>{{ $t('material.uploadTips') }}</div>
+        </uploader>
+   
+        <div slot="footer" class="dialog-footer">
+          <el-button :title="$t('common.nocompleteWillEmpty')" @click="close">{{ $t('common.close') }}</el-button>
+        </div>
+      </el-dialog>
+    </div>
+  </template>
+   
+  <script>
+  import { getCookie } from '@/prototypeEx/cacheEx'
+  export default {
+    filters: {},
+    props: {
+      dirId: {
+        // 上传文件夹id
+        type: Number,
+        default: 0
+      },
+      show: {
+        type: Boolean,
+        default: false
+      },
+      uploadUrl: {
+        type: String,
+        default: '',
+        required: true
+      }
+    },
+    data() {
+      return {
+        selectFile_loading: false,
+        visible: this.show,
+        title: this.$t('common.upload'),
+        dialogLoading: false,
+        MineType: [
+          'image/png',
+          'image/jpg',
+          'image/jpeg',
+          'image/gif',
+          'image/webp',
+          'application/x-msdownload',
+          'application/vnd.android.package-archive'
+        ], // 定义可接受的文件类型
+        options: {
+          target: '/', //  目标上传 URL
+          testChunks: true, // 是否开启服务器分片校验,是否测试每个块是否在服务端已经上传了,主要用来实现秒传、跨浏览器上传等,默认 true
+          chunkSize: this.config.uploader_chunk_size, // 分块时按照该值来分10kb
+          fileParameterName: 'file', // 上传文件时文件的参数名,默认 file
+          maxChunkRetries: 3, // 最大自动失败重试上传次数
+          query: {
+            token: '', // 从vuex中拿到的token
+            dirId: this.dirId // 上传目标文件夹
+          },
+          checkChunkUploadedByResponse: function(chunk, message) {
+            // 服务器分片校验函数,秒传及断点续传基础,用于根据 XHR 响应内容检测每个块是否上传成功了
+            // let objMessage = JSON.parse(message);
+            // if (objMessage.skipUpload) {
+            //   return true;
+            // }
+            // return (objMessage.uploaded || []).indexOf(chunk.offset + 1) >= 0;
+          },
+          simultaneousUploads: 3 // 并发上传数,默认 3
+          // singleFile: true 是否开启单文件上传
+          // headers: {
+          //   token: "eddd7f17-f352-4d25-8bd6-541ef72e446e"
+          // }
+        },
+        attrs: {
+          accept:
+            'image/gif,image/png,image/jpg,image/jpeg,image/webp,application/octet-stream,.apk'
+        },
+        fileStatusText: {
+          success: this.$t('common.success'),
+          error: this.$t('common.error'),
+          uploading: this.$t('material.uploading'),
+          paused: this.$t('common.pause'),
+          waiting: this.$t('common.wait')
+        }
+      }
+    },
+    computed: {
+      uploader() {
+        return this.$refs.uploader.uploader // 实例化上传对象
+      }
+    },
+    watch: {
+      show(val, oldVal) {
+        if (val === oldVal) {
+          return
+        }
+        if (val) {
+          this.initData()
+        }
+        this.visible = val
+      },
+      // 如果内部有新值变化,更新外部的visible
+      visible(val, oldVal) {
+        if (val === oldVal) {
+          return
+        }
+        this.$emit('update:visible', val)
+      }
+    },
+    created() {
+    },
+    mounted() {
+      this.options.query.token = getCookie('token') // 加载后把vuex中的token赋值给上传组件的options
+    },
+    methods: {
+   
+      // 初始化上传地址问题
+      initData() {
+        this.options.target = this.uploadUrl
+        this.options.query.dirId = this.dirId
+      },
+      createUUID(file) {
+        // 生成文件的UUID作为唯一的标识符
+        // file.pause(); // 文件上传先暂停
+        const s = []
+        const hexDigits = '0123456789abcdef'
+        for (let i = 0; i < 36; i++) {
+          s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1)
+        }
+        s[14] = '4' // bits 12-15 of the time_hi_and_version field to 0010
+        s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1) // bits 6-7 of the clock_seq_hi_and_reserved to 01
+        s[8] = s[13] = s[18] = s[23] = '-'
+   
+        const uuid = s.join('')
+        file.uniqueIdentifier = uuid
+        // file.resume(); // 文件继续上传
+      },
+      onFileAdded(file) {
+        // 选择文件后
+        // this.computeMD5(file);
+        this.createUUID(file)
+        const index = this.MineType.indexOf(file.fileType)
+        if (index === -1) {
+          // 不在MINE自定义的文件格式类型中,不让上传;
+          file.ignored = true
+        }
+      },
+      onFileProgress(rootFile, file, chunk) {
+        // 上传中的回调函数
+      },
+      onFileSuccess(rootFile, file, response, chunk) {
+        // 文件上传成功后的回调
+        const res = JSON.parse(response)
+        // console.log(res);
+        if (res.success === 1) {
+          const para = {
+            data: {
+              parentId: this.dirId,
+              name: file.name,
+              identifier: res.data.identifier,
+              thumPic: res.data.t_identifier,
+              size: file.size,
+              resType: res.data.resType,
+              duration: res.data.duration,
+              serverCode: res.data.serverCode
+            }
+          }
+          this.urlmethod(this.url.material.add_res, para)
+            .then(res => {
+            })
+            .catch(err => {
+              console.log(err)
+            })
+          // 上传成功
+        } else {
+          this.$message({
+            message: res.errMsg,
+            type: 'warning'
+          })
+        }
+        // 服务器自定义的错误(即虽返回200,但是是错误的情况),这种错误是Uploader无法拦截的
+        // if (!res.result) {
+        //   this.$message({ message: res.message, type: "error" });
+        //   //文件状态设为“失败”
+        //   this.statusSet(file.id, "failed");
+        //   return;
+        // }
+   
+        // 如果服务端返回需要合并
+        // if (res.needMerge) {
+        //   // 文件状态设为“合并中”
+        //   this.statusSet(file.id, "merging");
+        //   api
+        //     .mergeSimpleUpload({
+        //       tempName: res.tempName,
+        //       fileName: file.name,
+        //       ...this.params
+        //     })
+        //     .then(res => {
+        //       // 文件合并成功
+        //       // Bus.$emit("fileSuccess");
+        //       this.statusRemove(file.id);
+        //     })
+        //     .catch(e => {});
+        //   不需要合并
+        // } else {
+        //   // Bus.$emit("fileSuccess");
+        //   console.log("上传成功");
+        // }
+      },
+      onFileError(rootFile, file, response, chunk) {
+        // 错误的回调
+        console.log(response)
+        // this.$message({
+        //   message: response,
+        //   type: "error"
+        // });
+      },
+      close() {
+        // 点击确认关闭上传框
+        this.uploader.cancel() // 点击关闭按钮后清空上传对象
+        // 这里调用父组件重新获取数据刷新列表的方法,重新获取容量
+        this.$parent.initMaterialPage(this.dirId)
+        this.visible = false
+      }
+    }
+  }
+  </script>
+  <style lang="scss" scoped>
+  .uploader-dialog-wrap {
+    .warning-message {
+      margin-top: 10px;
+      color: #F56C6C;
+      vertical-align: middle;
+    }
+  }
+  </style>
+  <style lang="scss">
+  .uploader-dialog-wrap {
+    .el-dialog {
+      .el-dialog__header {
+        // background-color: #42b983;
+        .el-dialog__title {
+          color: #333;
+          font-size: 24px;
+        }
+        .el-dialog__headerbtn .el-dialog__close {
+          color: #333;
+        }
+      }
+    }
+    .dialog-width {
+      min-width: 45rem !important;
+    }
+    .uploader-example {
+      // 上传组件外壳样式
+      // width: 880px;
+      padding: 15px;
+      // margin: 40px auto 0;
+      font-size: 12px;
+      // box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
+    }
+    .uploader-example .uploader-btn {
+      // 上传按钮样式
+      background-color: #409eff;
+      color: #fff;
+      border-color: #409eff;
+      padding: 7px 13px;
+      border-radius: 3px;
+      margin-bottom: 10px;
+    }
+    .uploader-example .uploader-btn:hover {
+      // 按钮hover样式
+      background-color: #66b1ff;
+      border-color: #66b1ff;
+    }
+    .el-button--danger {
+      background-color: #409EFF;
+      border-color: #409EFF;
+      &:hover {
+        background-color: #66b1ff;
+      border-color: #66b1ff;
+      }
+    }
+    .uploader-example .uploader-list {
+      // 上传文件列表样式
+      max-height: 440px;
+      overflow: auto;
+      overflow-x: hidden;
+      overflow-y: auto;
+    }
+    // 覆盖掉默认的文件图标样式
+    .uploader-file-icon[icon='image']:before {
+      content: '';
+    }
+    .uploader-file-icon[icon='image'] {
+      background: url(../../../assets/image-icon.png);
+    }
+    .uploader-file-icon[icon='document']:before {
+      content: '';
+    }
+    .uploader-file-icon[icon='document'] {
+      background: url(../../../assets/text-icon.png);
+    }
+    .el-dialog__body {
+      padding: 5px;
+    }
+  }
+  </style>
+   

+ 83 - 0
src/view/fileManager/components/viewer-dialog.vue

@@ -0,0 +1,83 @@
+<!-- 图片预览组件dailog形式 -->
+<template>
+    <div class="viewer-dialog-wrap">
+      <el-dialog
+        :visible.sync="visible"
+        :title="imgTitle"
+        :show="show"
+        custom-class="dialog-width"
+        @close="$emit('update:show', false)"
+      >
+        <img :src="src" alt />
+        <!-- <div slot="footer" class="dialog-footer">{{imgTitle}}</div> -->
+      </el-dialog>
+    </div>
+  </template>
+   
+  <script>
+  export default {
+    name: 'ViewerDialog',
+    filters: {},
+    props: {
+      id: {
+        type: String,
+        default: ''
+      },
+      show: {
+        type: Boolean,
+        default: false
+      },
+      src: {
+        type: String,
+        default: ''
+      },
+      imgTitle: {
+        type: String,
+        default: ''
+      }
+    },
+    data() {
+      return {
+        visible: this.show
+      }
+    },
+    computed: {},
+    watch: {
+      show(val, oldVal) {
+        if (val === oldVal) {
+          return
+        }
+        this.visible = val
+      },
+      // 如果内部有新值变化,更新外部的visible
+      visible(val, oldVal) {
+        if (val === oldVal) {
+          return
+        }
+        this.$emit('update:visible', val)
+        if (val === false) {
+          // 当关闭弹窗的时候,向父组件传递清空src的消息
+          this.$emit('closeImgDialog')
+        }
+      }
+    },
+    created() {},
+    mounted() {},
+    methods: {
+      inited(viewer) {
+        this.$viewer = viewer
+      }
+    }
+  }
+  </script>
+  <style lang="scss">
+  .viewer-dialog-wrap {
+    .dialog-width {
+      img {
+        width: 100%;
+        height: 100%;
+      }
+    }
+  }
+  </style>
+   

+ 779 - 0
src/view/fileManager/qiniuTransfer copy.vue

@@ -0,0 +1,779 @@
+<!--多媒体素材首页 -->
+<template>
+  <div class="video-container">
+    <el-card shadow="hover">
+      <div class="video-header clearfix">
+        <div class="header-top">
+          <el-button
+            :loading="uploadeFile_loading"
+            type="primary"
+            size="medium"
+            @click="uploadeFile"
+          >
+            <i class="el-icon-upload2"></i>
+            <!-- 上传 -->
+            {{ $t("material.upload") }}
+          </el-button>
+          <!-- 新建文件夹 -->
+          <el-button type="primary" size="medium" @click="addFolder">
+            <i class="el-icon-plus"></i>
+            {{ $t("material.newFolder") }}
+          </el-button>
+          <!-- 重命名 -->
+          <el-button
+            v-show="activeFlag"
+            :disabled="activeFlagNotReame"
+            style="margin-left: 10px"
+            type="primary"
+            size="medium"
+            @click="handleRenameFile"
+          >
+            <i class="el-icon-edit-outline"></i>
+            {{ $t("material.rename") }}
+          </el-button>
+          <!-- 移动到 -->
+          <el-button
+            v-show="activeFlag"
+            :disabled="activeFlagMoveble"
+            style="margin-left: 10px"
+            type="primary"
+            size="medium"
+            @click="moveFolder"
+          >
+            <i class="el-icon-rank"></i>
+            {{ $t("material.moveTo") }}
+          </el-button>
+
+          <!-- 全选 -->
+          <el-button
+            v-show="activeFlag"
+            type="primary"
+            style="margin-left: 10px"
+            size="medium"
+            @click="toggleCheckAllSelect"
+          >
+            <i class="el-icon-check"></i>
+            {{ $t("material.selectAll") }}
+          </el-button>
+          <!-- 删除 -->
+          <el-button
+            v-show="activeFlag"
+            style="margin-left: 10px"
+            size="medium"
+            @click="handleDeleteFile"
+          >
+            <i class="el-icon-delete"></i>
+            {{ $t("material.delete") }}
+          </el-button>
+          <div class="fr">
+            <el-radio-group v-model="resType" @change="queryMaterialPage">
+              <!-- 全部 -->
+              <el-radio label="-1">{{ $t("material.all") }}</el-radio>
+              <!-- 图片 -->
+              <el-radio label="1">{{ $t("material.image") }}</el-radio>
+              <!-- 应用 -->
+              <el-radio label="98">{{ $t("programModel.apply") }}</el-radio>
+            </el-radio-group>
+            <el-input
+              v-model="keyWord"
+              :placeholder="$t('common.name')"
+              style="width: 150px; margin-left: 10px"
+              size="medium"
+              clearable
+              @clear="resetGetMaterialPage"
+            ></el-input>
+            <!-- 查询 -->
+            <el-button
+              size="medium"
+              type="primary"
+              style="margin-left: 2px"
+              icon="el-icon-search"
+              @click="queryMaterialPage"
+              >{{ $t("material.search") }}</el-button
+            >
+          </div>
+        </div>
+
+        <div class="breadcrumb">
+          <!-- 面包屑 -->
+          <el-breadcrumb separator-class="el-icon-arrow-right">
+            <el-breadcrumb-item
+              v-for="(item, index) in breadcrumbList"
+              :key="index"
+            >
+              <span
+                :class="
+                  index === breadcrumbList.length - 1
+                    ? 'breadcrumb-link-active'
+                    : ''
+                "
+                class="breadcrumb-link"
+                @click="backFileFolder(item)"
+                >{{ item.name }}</span
+              >
+            </el-breadcrumb-item>
+          </el-breadcrumb>
+        </div>
+      </div>
+
+      <div v-loading="loading" class="video-main">
+        <ul class="list">
+          <li
+            v-for="(file, index) in files"
+            :key="index"
+            :class="{ active: file.active }"
+            class="list-item"
+            @dblclick="dbClickOpenFile(file)"
+          >
+            <div class="inner">
+              <el-image
+                v-if="file.resType > 0"
+                :src="file.thumUrl ? file.thumUrl : defultThumUrl"
+                class="icon-thumb"
+                fit="contain"
+                alt
+              ></el-image>
+              <i v-else class="icon-folder"></i>
+              <div v-show="file.resType > 0" class="hover-cover">
+                <span style="color: #fff">{{ file.size | sizeFilter }}</span>
+              </div>
+            </div>
+            <i
+              class="icon-file-selected"
+              @click="toggleSelect(file, file.id)"
+            ></i>
+            <div class="file-name">
+              <span :title="file.name">{{ file.name }}</span>
+            </div>
+          </li>
+        </ul>
+        <!-- 分页 -->
+        <el-pagination
+          :current-page="pageIndex"
+          :hide-on-single-page="true"
+          :page-sizes="[100, 200, 400, 600]"
+          :page-size="100"
+          :total="total"
+          layout="total,  prev, pager, next, jumper"
+          @current-change="handleCurrentChange"
+        ></el-pagination>
+      </div>
+    </el-card>
+    <!-- 重命名弹出框 -->
+    <el-dialog
+      :title="$t('common.rename')"
+      :visible.sync="renameDialogVisible"
+      width="30%"
+    >
+      <el-form
+        ref="renameForm"
+        :model="renameForm"
+        :rules="renameRules"
+        style="margin-top: 20px"
+      >
+        <el-form-item prop="name">
+          <el-input v-model="renameForm.name" autocomplete="off"></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button size="medium" @click="renameDialogVisible = false">{{
+          $t("common.cancel")
+        }}</el-button>
+        <el-button
+          :loading="rename_loading"
+          type="primary"
+          size="medium"
+          @click="handleRenameConfirm"
+          >{{ $t("common.confirm") }}</el-button
+        >
+      </div>
+    </el-dialog>
+    <!-- 上传组件 -->
+    <uploader-dialog
+      :show.sync="showDialog"
+      :upload-url="upfileUrl"
+      :dir-id="parentId"
+    ></uploader-dialog>
+    <!-- 移动文件组件 -->
+    <move-file-dialog
+      :show.sync="moveFileDialog"
+      :ids="activeItems"
+      :parent-id="parentId"
+      @removeActiveItem="handleRemoveActiveItem"
+    ></move-file-dialog>
+    <!-- 图片弹出放大组件 -->
+    <viewer-dialog
+      :show.sync="showImageDialog"
+      :src="imgSrc"
+      :img-title="imgTitle"
+      @closeImgDialog="imgDialogClose"
+    ></viewer-dialog>
+    <!-- 视频播放组件 -->
+    <el-dialog
+      :visible.sync="showlPlayVideo"
+      :append-to-body="true"
+      @close="closePlay"
+    >
+      <player :video-url="videoUrl" :state="state" :poster="poster"></player>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import Vue from "vue";
+// 引入上传子组件dialog
+import uploaderDialog from "./components/uploader-dialog";
+// 引入移动文件子组件dialog
+import moveFileDialog from "./components/movefile-dialog";
+// 引入图片子组件dialog
+import viewerDialog from "./components/viewer-dialog";
+// 引入视频播放组件
+import player from "@/components/Video-player";
+export default {
+  name: "Videomanagement",
+  components: {
+    uploaderDialog,
+    moveFileDialog,
+    viewerDialog,
+    player,
+  },
+  filters: {
+    sizeFilter($bytesize) {
+      let $i = 0;
+      while (Math.abs($bytesize) >= 1024) {
+        $bytesize = $bytesize / 1024;
+        $i++;
+        if ($i === 4) break;
+      }
+      const $units = ["Bytes", "KB", "MB", "GB", "TB"];
+      const $newsize = Math.round($bytesize, 2);
+      return $newsize + " " + $units[$i];
+    },
+  },
+  data() {
+    return {
+      uploadeFile_loading: false,
+      rename_loading: false,
+      defultThumUrl: "../../assets/svg/icon-file-thumbnail.svg", // 默认文件夹的样式图片
+      loading: false, // 加载loading样式
+      keyWord: "", // 查询关键字
+      resType: "-1", // 资源类型查询条件
+      id: 0, // 当前目录id
+      parentId: 0, // 当前目录的父文件夹id
+      upfileUrl: "", // 上传文件服务器的url地址
+      showDialog: false, // 是否弹出上传dialog
+      moveFileDialog: false, // 是否弹出移动文件dialog
+      showImageDialog: false, // 弹出大图浏览dialog
+      imgSrc: "", // 弹出大图的图片url地址
+      imgTitle: "", // 弹出大图的图片title
+      showlPlayVideo: false, // 弹出视频播放
+      videoUrl: "", // 视频播放地址
+      state: false, // 视频播放状态
+      poster: "", // 视频播放的封面
+      activeFlag: false, // 用来显示关闭删除,重命名,移动到按钮操作
+      activeFlagNotReame: false, // 当激活多个元素的时候,重命名操作灰掉
+      activeFlagMoveble: false, // 当激活选中的元素中有文件夹的时候,移动操作不可用,灰掉
+      activeItems: [], // 选中激活的文件列表
+      files: [], // 文件数据列表
+      folderListData: [], // 文件夹列表数据
+      breadcrumbList: [], // 面包屑中保存的文件夹数据
+      toggleCheckAllSelectFlag: false, // 全选样式切换
+      pageIndex: 1, // 分页参数-当前页
+      pageSize: 100, // 分页参数-分页大小
+      total: 0, // 分页参数-总条数
+      storagePercent: 0, // 存储空间容量百分比
+      maxStorage: 0, //  存储空间总容量
+      useStorage: 0, // 存储空间已用容量
+      renameDialogVisible: false,
+      renameForm: {
+        name: "",
+      },
+      renameRules: {
+        name: {
+          required: true,
+          pattern: /^[^/\\\\:\\*\\?\\<\\>\\|\"]{1,255}$/,
+          message: this.$t("material.incorrectFileNameTips"), // 请输入正确的文件名称
+          trigger: "blur",
+        },
+      },
+    };
+  },
+  computed: {},
+  created() {
+    this.initMaterialPage();
+    this.getFolderList(); // 获取文件夹列表数据
+  },
+  mounted() {},
+  methods: {
+    handleCurrentChange(val) {
+      this.pageIndex = val;
+      this.initMaterialPage(this.parentId);
+    },
+    uploadeFile() {
+      this.uploadeFile_loading = true;
+      // 上传文件
+      this.urlmethod(this.url.usermanagement.serverAddr_servers, null)
+        .then((res) => {
+          this.upfileUrl = res.data.uploadUrl;
+          this.showDialog = true;
+          this.uploadeFile_loading = false;
+        })
+        .catch((err) => {
+          this.uploadeFile_loading = false;
+          console.log("err", err);
+          this.loading = false;
+        });
+    },
+    moveFolder() {
+      // 点击移动文件按钮,弹出移动文件dialog
+      this.moveFileDialog = true;
+    },
+    toggleSelect(item, id) {
+      // 切换选择文件或文件夹的激活样式
+      this.id = id;
+      if (item.active) {
+        Vue.set(item, "active", false); // 为item添加不存在的属性,需要使用vue提供的Vue.set( object, key, value )方法
+        const index = this.activeItems.indexOf(id);
+        if (index > -1) {
+          this.activeItems.splice(index, 1);
+        }
+      } else {
+        Vue.set(item, "active", true);
+        this.activeItems.push(id);
+      }
+      if (this.activeItems.length > 0) {
+        // 当有文件被激活时,显示重命名,删除,移动操作按钮
+        this.activeFlag = true;
+      } else {
+        this.activeFlag = false;
+      }
+      if (this.activeItems.length > 1) {
+        // 当有两个以上的文件被选中的时候,重命名,移动操作按钮不可用
+        this.activeFlagNotReame = true;
+      } else {
+        this.activeFlagNotReame = false;
+      }
+      this.activeFlagMoveble = true;
+      this.files.forEach((item) => {
+        if (item.active) {
+          if (item.resType !== 0) {
+            // 只要有一个不是文件夹的被选中,就可以移动
+            this.activeFlagMoveble = false;
+          }
+        }
+      });
+    },
+    toggleCheckAllSelect() {
+      // 全选切换
+      this.activeFlagMoveble = !this.activeFlagMoveble; // 全选移动操作可用,切换取反
+      if (!this.toggleCheckAllSelectFlag) {
+        this.files.forEach((item) => {
+          if (!item.active) {
+            Vue.set(item, "active", true);
+          }
+        });
+        this.toggleCheckAllSelectFlag = true;
+      } else {
+        this.files.forEach((item) => {
+          if (item.active) {
+            Vue.set(item, "active", false);
+          }
+        });
+        this.toggleCheckAllSelectFlag = false;
+      }
+      this.activeItems = [];
+      this.files.forEach((item) => {
+        if (item.active) {
+          this.activeItems.push(item.id);
+          if (item.resType !== 0) {
+            // 只要有一个不是文件夹的被选中,就可以移动
+            this.activeFlagMoveble = false;
+          }
+        }
+      });
+      // 当没有选项被选中的时候
+      if (this.activeItems.length === 0) {
+        this.activeFlag = false;
+        this.activeFlagNotReame = false;
+      }
+    },
+    initMaterialPage(id = 0) {
+      // 初始化获取素材管理分页(可以通过传递文件夹id来获取对应的文件列表,默认值0,获取的是根目录)
+      this.loading = true;
+      const para = {
+        data: {
+          pageIndex: this.pageIndex,
+          pageSize: this.pageSize,
+          parentId: id,
+          resType: Number(this.resType),
+          keyWord: this.keyWord,
+        },
+      };
+      this.urlmethod(this.url.material.list_res, para)
+        .then((res) => {
+          this.files = [...res.data.list];
+          this.loading = false;
+          this.total = res.data.recordTotal;
+          this.activeItems = []; // 激活选项空
+          this.activeFlag = false; // 可操作按钮隐藏
+          this.activeFlagMoveble = false; // 恢复能不能移动的初始值
+        })
+        .catch((err) => {
+          console.log("err", err);
+          this.loading = false;
+        });
+    },
+    queryMaterialPage() {
+      // 通过条件筛选查询获取文件列表,也需要把当前文件夹的id传递进去
+      this.initMaterialPage(this.parentId);
+    },
+    resetGetMaterialPage() {
+      // 点击搜索框清楚按钮,重新获取列表数据
+      // 把当前的文件夹id传进去
+      this.initMaterialPage(this.parentId);
+    },
+    getFolderList() {
+      // 获取文件夹列表数据
+      this.urlmethod(this.url.material.selectDir_res, null)
+        .then((res) => {
+          this.folderListData.push(res.data);
+          const temObj = {};
+          temObj.id = this.folderListData[0].id;
+          temObj.name = this.folderListData[0].name;
+          temObj.parentId = this.folderListData[0].parentId;
+          this.breadcrumbList.push(temObj); // 这里只保存了根目录文件夹
+        })
+        .catch((err) => {
+          console.log("err", err);
+          this.loading = false;
+        });
+    },
+    backFileFolder(item) {
+      // 点击面包屑回退到对应的文件夹级别,并且分页的索引值也需要退回到第一页
+      this.pageIndex = 1;
+      const index = this.breadcrumbList.indexOf(item);
+      const length = this.breadcrumbList.length;
+      if (item.id === this.breadcrumbList[length - 1].id) {
+        // 点击的元素id是最后一个文件id,不能删除
+      } else {
+        this.breadcrumbList.splice(index + 1);
+      }
+      this.initMaterialPage(item.id); // 点击面包屑中的哪个文件夹就获取对应的文件列表页
+      this.parentId = item.id; // 更新当前界面的父文件夹id
+    },
+    addFolder() {
+      // 新增文件夹
+      this.$prompt(null, this.$t("common.add"), {
+        confirmButtonText: this.$t("common.confirm"),
+        cancelButtonText: this.$t("common.cancel"),
+        inputPlaceholder: this.$t("material.enterFolderNameTips"),
+        inputPattern: /^[^/\\\\:\\*\\?\\<\\>\\|\"]{1,255}$/, // 文件名正则
+        inputErrorMessage: this.$t("material.incorrectFileNameTips"), // 文件名格式不正确
+      })
+        .then(({ value }) => {
+          const para = {
+            data: {
+              name: value,
+              parentId: this.parentId,
+            },
+          };
+          this.urlmethod(this.url.material.addDir_res, para)
+            .then(() => {
+              this.initMaterialPage(this.parentId);
+              this.$message({
+                type: "success",
+                message: this.$t("material.newFolderNameIs") + value, // 新的文件名是
+              });
+            })
+            .catch((err) => {
+              console.log("err", err);
+            });
+        })
+        .catch(() => {
+          this.$message({
+            type: "info",
+            message: this.$t("common.canceled"),
+          });
+        });
+    },
+    // 打开重命名弹窗
+    handleRenameFile() {
+      // 文件重命名操作
+      // 当激活项里只有唯一的一个元素,遍历files,通过id就可以找到该项需要重命名的name
+      this.files.forEach((v) => {
+        if (this.activeItems.indexOf(v.id) === 0) {
+          this.renameForm.name = v.name;
+        }
+      });
+      this.renameDialogVisible = true;
+    },
+    // 重命名弹窗确定提交
+    handleRenameConfirm() {
+      this.$refs["renameForm"].validate((valid) => {
+        if (valid) {
+          this.rename_loading = true;
+          const para = {
+            data: {
+              id: this.id,
+              name: this.renameForm.name,
+            },
+          };
+          this.urlmethod(this.url.material.reName_res, para)
+            .then(() => {
+              // 重命名成功后重新获取列表
+              this.initMaterialPage(this.parentId);
+              this.$message({
+                type: "success",
+                message:
+                  this.$t("material.newFolderNameIs") + this.renameForm.name,
+              });
+              this.renameDialogVisible = false;
+              this.rename_loading = false;
+            })
+            .catch((err) => {
+              this.rename_loading = false;
+              console.log("err", err);
+            });
+        } else {
+          return false;
+        }
+      });
+    },
+    handleDeleteFile() {
+      // 删除文件
+      this.$confirm(
+        this.$t("common.tipsBeforeDelete"),
+        this.$t("common.tips"),
+        {
+          confirmButtonText: this.$t("common.confirm"),
+          cancelButtonText: this.$t("common.cancel"),
+          type: "warning",
+        }
+      )
+        .then(() => {
+          this.loading = true;
+          // 执行删除文件的api
+          const para = {
+            data: {
+              ids: this.activeItems,
+            },
+          };
+          this.urlmethod(this.url.material.delete_res, para)
+            .then(() => {
+              // 删除成功后重新获取列表,注意,这是不是this.id,而是父id,因为点击文件夹了,当前的id已经发生了改变
+              this.initMaterialPage(this.parentId);
+              this.activeItems = []; // 激活选项空
+              this.activeFlag = false; // 可操作按钮隐藏
+              this.$message({
+                type: "success",
+                message: this.$t("common.deleteSuccess"),
+              });
+              this.loading = false;
+            })
+            .catch((err) => {
+              this.loading = false;
+              console.log("err", err);
+            });
+        })
+        .catch(() => {
+          this.$message({
+            type: "info",
+            message: this.$t("common.canceled"),
+          });
+        });
+    },
+    handleRemoveActiveItem(removeId) {
+      // 子组件把文件移动位置成功后触发这个绑定的事件处理函数
+      this.activeItems = []; // 激活选项空
+      this.activeFlag = false; // 可操作按钮隐藏
+    },
+    dbClickOpenFile(file) {
+      // 双击文件操作
+      // 双击后记住当前文件的id
+      this.id = file.id;
+      if (file.resType === 0) {
+        // 打开的是文件夹
+        const temObj = {};
+        temObj.id = file.id;
+        temObj.name = file.name;
+        temObj.parentId = file.parentId;
+        this.breadcrumbList.push(temObj); // 双击文件夹把当前文件夹的信息push到面包屑列表中
+        this.parentId = file.id; // 进入文件夹后,此时当前的父id就应该修改为双击文件夹的那个id
+        this.initMaterialPage(this.id);
+      } else if (file.resType === 1) {
+        // 打开的是图片
+        this.showImageDialog = true;
+        this.imgSrc = file.url;
+        this.imgTitle = file.name;
+      } else if (file.resType === 2 || file.resType === 99) {
+        // 打开的是视频
+        this.showlPlayVideo = true;
+        this.videoUrl = file.url;
+        this.state = true;
+        this.poster = file.thumUrl;
+      } else {
+        // 其他文件的操作
+        // 暂不支持
+      }
+    },
+    closePlay() {
+      // 关闭视频播放弹窗
+      this.state = false;
+      this.videoUrl = "";
+    },
+    imgDialogClose() {
+      // 子组件发出图片弹窗关闭,这里需要清空传入的图片地址,fix在慢网速的情况下,会先看到上一次的图片。
+      this.imgSrc = "";
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.clearfix:after {
+  content: "";
+  display: block;
+  clear: both;
+}
+.video-container {
+  min-width: 630px;
+  margin: 10px;
+  .video-header {
+    padding: 0 0 5px 0;
+    border-bottom: 1px solid #dbdbdb;
+    .breadcrumb {
+      // float: left;
+      height: 20px;
+      margin-top: 10px;
+      .breadcrumb-link {
+        cursor: pointer;
+        //font-size: 16px;
+      }
+      .breadcrumb-link:hover {
+        color: #409eff;
+        text-decoration: underline;
+      }
+      .breadcrumb-link-active {
+        // 面包屑当前激活文件夹的样式
+        font-weight: 700;
+      }
+    }
+    .header-top {
+      // float: right;
+      height: 40px;
+      line-height: 40px;
+      position: relative;
+    }
+  }
+  .video-main {
+    .list-item {
+      border: 1px solid #fff;
+      box-sizing: border-box;
+      position: relative;
+      height: 100px;
+      width: 80px;
+      // background-color: green;
+      margin: 5px;
+      display: inline-block;
+      cursor: pointer;
+      .inner {
+        height: 60px;
+        width: 60px;
+        // background-color: red;
+        margin: 5px 10px;
+        // padding: 10px 15px 10px 15px;
+        .icon-folder {
+          // 文件夹的样式
+          display: inline-block;
+          width: 60px;
+          height: 60px;
+          background-image: url(../../assets/svg/icon-file-close.svg);
+          background-size: 100% 100%;
+        }
+        .icon-thumb {
+          // 文件的样式
+          width: 60px;
+          height: 60px;
+        }
+      }
+      .file-name {
+        // 文件夹name样式
+        padding-left: 10px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+        color: #424e67;
+        font-size: 12px;
+      }
+      .file-name:hover {
+        color: #409eff;
+      }
+    }
+    .hover-cover {
+      width: 60px;
+      height: 60px;
+      position: absolute;
+      left: 10px;
+      top: 5px;
+      background-color: rgb(0, 0, 0);
+      opacity: 0;
+      text-align: center;
+      line-height: 60px;
+      font-size: 12px;
+    }
+    .list-item:hover {
+      background-color: #f1f5fa;
+      .icon-file-selected {
+        opacity: 0.5;
+      }
+      .hover-cover {
+        opacity: 0.6;
+      }
+    }
+    .icon-file-selected {
+      // 小圆点默认样式
+      position: absolute;
+      left: 5px;
+      top: 5px;
+      display: inline-block;
+      width: 20px;
+      height: 20px;
+      background-size: 100% 100%;
+      background-image: url(../../assets/svg/icon-file-selected.svg);
+      opacity: 0;
+    }
+    .icon-file-selected:hover {
+      // 小圆点hover
+      opacity: 1 !important;
+    }
+    .active {
+      // 选择文件触发激活样式
+      border: 1px solid #409eff;
+      border-radius: 8px;
+      .icon-file-selected {
+        position: absolute;
+        left: 5px;
+        top: 5px;
+        display: inline-block;
+        width: 20px;
+        height: 20px;
+        background-size: 100% 100%;
+        background-image: url(../../assets/svg/icon-file-selected.svg);
+        opacity: 1;
+      }
+    }
+    .active:hover {
+      // 激活状态小圆点透明度1
+      .icon-file-selected {
+        opacity: 1 !important;
+      }
+    }
+    .loadding-message {
+      // 加载loading的文字样式
+      color: #424e67;
+      font-size: 12px;
+      text-align: center;
+    }
+  }
+}
+</style>

Plik diff jest za duży
+ 1219 - 0
src/view/fileManager/qiniuTransfer.vue