Kaynağa Gözat

【我的素材】开发新版上传列表组件

任一存 4 yıl önce
ebeveyn
işleme
1ca279713d

BIN
src/assets/images/icons/material_preview_upload_cancel@2x.png


BIN
src/assets/images/icons/upload-file-type-icon-audio@2x.png


BIN
src/assets/images/icons/upload-file-type-icon-image@2x.png


BIN
src/assets/images/icons/upload-file-type-icon-video@2x.png


+ 271 - 0
src/views/material/components/uploadList1.1.0.vue

@@ -0,0 +1,271 @@
+<template>
+  <!-- 这是一个简单组件,只关注视图层 -->
+  <div class="upload-list-component">
+    <div class="head">
+      <div class="left">
+        <i class="iconfont iconmaterial_preview_upload"></i>
+        <span class="text">正在上传 {{successNumber}}/{{taskList.length}}</span>
+      </div>
+      <div class="right">
+        <!-- <span></span> -->
+        <i
+          class="iconfont icon-material_preview_upload_collect"
+          :class="this.expandSwitch ? '' : 'upsideDown'"
+          @click="onClickExpand"></i>
+      </div>
+    </div>
+    <div class="content" v-show="expandSwitch">
+      <div class="list-item"  v-for="(taskItem, index) in taskList" :key="index">
+        <div class="left">
+          <img class="type-icon" :src="uploadFieIconUrl" alt=""/>
+          <span class="text">{{taskItem.title}}</span>
+        </div>
+        <div class="right">
+          <span :class="{
+            'text-success': taskItem.status === 'SUCCESS',
+            'text-fail': taskItem.status === 'FAIL',
+            'text-loading': taskItem.status === 'LOADING',
+          }">
+            {{taskItem.statusText}}
+          </span>
+          <span class="progress-text">{{taskItem.progress}}%</span>
+          <img
+            class="cancel-btn"
+            :src="require('@/assets/images/icons/material_preview_upload_cancel@2x.png')"
+          />
+        </div>
+        <div class="progress-bar" v-if="taskItem.ifKnowProgress" :style="{width: taskItem.progress + '%'}"></div>
+        <div class="progress-bar-unknown" v-else></div>
+      </div>
+    </div>
+
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    fileType: {
+      type: String,
+      default: 'IMAGE', // 'IMAGE' | 'AUDIO' | 'VIDEO'
+    },
+    taskList: {
+      /**
+       * 每个元素的内部结构:{
+       *  title: String
+       *  ifKnowProgress: Boolean // false则进度条效果是loading而不是具体进度
+       *  progress:Number // 进度条,为负数的话会显示一个loading效果但不显示真实进度。
+       *  status: 'SUCCESS' | 'FAIL' | 'LOADING' // 只影响statusText的样式,以及是否显示进度条。
+       *  statusText
+       * }
+       */
+      type: Array,
+      default: () => []
+      // default: () => [
+      //   {
+      //     title: '标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题',
+      //     ifKnowProgress: true,
+      //     progress: 100,
+      //     status: 'SUCCESS',
+      //     statusText: '成功',
+      //   },
+      //   {
+      //     title: '标题',
+      //     ifKnowProgress: true,
+      //     progress: 30,
+      //     status: 'LOADING',
+      //     statusText: '上传中',
+      //   },
+      //   {
+      //     title: '标题',
+      //     ifKnowProgress: false,
+      //     progress: 30,
+      //     status: 'LOADING',
+      //     statusText: '上传中',
+      //   },
+      //   {
+      //     title: '标题',
+      //     ifKnowProgress: true,
+      //     progress: 55,
+      //     status: 'FAIL',
+      //     statusText: '失败',
+      //   }
+      // ]
+    },
+  },
+  computed: {
+    uploadFieIconUrl() {
+      switch (this.fileType) {
+        case 'IMAGE':
+          return require('@/assets/images/icons/upload-file-type-icon-image@2x.png')
+        case 'AUDIO':
+          return require('@/assets/images/icons/upload-file-type-icon-audio@2x.png')
+        case 'VIDEO':
+          return require('@/assets/images/icons/upload-file-type-icon-video@2x.png')
+        default:
+          return require('@/assets/images/icons/upload-file-type-icon-image@2x.png')
+      }
+
+    },
+    successNumber() {
+      return this.taskList.filter((item) => item.status === 'SUCCESS').length
+    }
+  },
+  data() {
+    return {
+      expandSwitch: true,
+    }
+  },
+  methods: {
+    onClickExpand() {
+      this.expandSwitch = !this.expandSwitch
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.upload-list-component {
+  width: 550px;
+  background: #FFFFFF;
+  box-shadow: 0px 4px 12px 0px rgba(0, 0, 0, 0.1);
+  border-radius: 4px;
+  border: 1px solid #E4E7ED;
+  .head {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    height: 60px;
+    padding: 0 26px;
+    border-bottom: 1px solid #EBEDF0;
+    .left {
+      display: flex;
+      align-items: center;
+      .iconmaterial_preview_upload {
+        color: @color;
+        font-size: 30px;
+        margin-right: 10px;
+        animation: spin 2s linear infinite;
+      }
+      .text {
+        font-size: 14px;
+        font-family: MicrosoftYaHei;
+        color: #323233;
+        line-height: 19px;
+      }
+    }
+    .right {
+      display: flex;
+      align-items: center;
+      i {
+        color: #979797;
+        cursor: pointer;
+        font-size: 12px;
+        transition: transform 0.2s;
+        &.upsideDown {
+          transform: rotate(180deg);
+        }
+      }
+    }
+  }
+  .content {
+    padding-left: 26px;
+    padding-right: 26px;
+    .list-item {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      height: 60px;
+      border-bottom: 1px solid #EBEDF0;
+      position: relative;
+      overflow: hidden;
+      .left {
+        display: flex;
+        align-items: center;
+        width: 60%;
+        .type-icon {
+          width: 28px;
+          height: 28px;
+          margin-right: 10px;
+          object-fit: contain;
+        }
+        .text {
+          font-size: 14px;
+          font-family: MicrosoftYaHei;
+          color: #323233;
+          line-height: 19px;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          word-break: keep-all;
+          white-space: nowrap;
+          max-width: 90%;
+        }
+      }
+      .right {
+        display: flex;
+        justify-content: flex-end;
+        align-items: center;
+        width: 40%;
+        .text-success {
+          margin-right: 10px;
+          font-size: 12px;
+          font-family: MicrosoftYaHei;
+          color: #969799;
+        }
+        .text-fail {
+          margin-right: 10px;
+          font-size: 12px;
+          font-family: MicrosoftYaHei;
+          color: #FA5555;
+        }
+        .text-loading {
+          margin-right: 10px;
+          font-size: 12px;
+          font-family: MicrosoftYaHei;
+          color: #969799;
+        }
+        .progress-text {
+          margin-right: 10px;
+          font-size: 12px;
+          font-family: MicrosoftYaHei;
+          color: #969799;
+        }
+        img {
+          width: 18px;
+          height: 18px;
+          cursor: pointer;
+        }
+      }
+      .progress-bar {
+        position: absolute;
+        left: 0;
+        bottom: 0;
+        height: 2px;
+        background: linear-gradient(144deg, #00AEFB 0%, @color 100%);
+      }
+      .progress-bar-unknown {
+        position: absolute;
+        left: 0;
+        bottom: 0;
+        height: 2px;
+        background: linear-gradient(144deg, #00AEFB 0%, @color 100%);
+        width: 330px;
+        animation: marquee 10s linear infinite
+      }
+    }
+  }
+}
+@keyframes spin {
+  100% {
+    transform: rotate(360deg)
+  }
+}
+@keyframes marquee {
+  0% {
+    transform: translateX(-100%)
+  }
+  100% {
+    transform: translateX(496px)
+  }
+}
+</style>