|
|
@@ -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>
|