|
@@ -4,76 +4,79 @@
|
|
|
<div class="teach-content-main">
|
|
|
<!--文件分类列表-->
|
|
|
<div class="content-type-list">
|
|
|
- <div :class="item.type === activeType ? 'content-type-item content-type-item-active':'content-type-item'" v-for="(item,index) in contentTypeList" :key="index" @click="selectFileType(index)">
|
|
|
- <Icon v-if="item.icon.indexOf('iconfont') != -1" :custom="item.icon" color="white" size="20" />
|
|
|
- <Icon v-else :type="item.icon" color="white" size="20" />
|
|
|
- <span class="content-type-label">{{item.label}}</span>
|
|
|
- <Tooltip transfer theme="light" :content="$t('teachContent.resTips')" :max-width="248" placement="bottom" offset="-20">
|
|
|
- <Icon type="ios-alert-outline" color="#1cc0f3" size="20" v-if="index == 0" style="position:absolute;top:-16px;margin-left:5px;" />
|
|
|
- </Tooltip>
|
|
|
- </div>
|
|
|
- <!-- Blob空间计算 -->
|
|
|
- <div :class="($access.can('admin.*|content-school-upd') || routerScope == 'private') ? 'space-box animated fadeIn fast' : 'space-box animated fadeOut fast'">
|
|
|
- <div class="percent-box">
|
|
|
- <span class="percent-item-span storage-full" :style="{ width: '100%' }" v-if="sizeInfo.total > storageSpace"></span>
|
|
|
- <span class="percent-item-span storage-res" :style='{ width: getPercent(sizeInfo.res) }'></span>
|
|
|
- <span class="percent-item-span storage-image" :style='{ width: getPercent(sizeInfo.image) }'></span>
|
|
|
- <span class="percent-item-span storage-video" :style='{ width: getPercent(sizeInfo.video) }'></span>
|
|
|
- <span class="percent-item-span storage-audio" :style='{ width: getPercent(sizeInfo.audio) }'></span>
|
|
|
- <span class="percent-item-span storage-doc" :style='{ width: getPercent(sizeInfo.doc) }'></span>
|
|
|
- <span class="percent-item-span storage-other" :style='{ width: getPercent(sizeInfo.other) }'></span>
|
|
|
- <span class="percent-item-span storage-data" :style='{ width: getPercent(sizeInfo.data) }'></span>
|
|
|
+ <vuescroll>
|
|
|
+ <div :class="item.type === activeType ? 'content-type-item content-type-item-active':'content-type-item'" v-for="(item,index) in contentTypeList" :key="index" @click="selectFileType(index)">
|
|
|
+ <Icon v-if="item.icon.indexOf('iconfont') != -1" :custom="item.icon" color="white" size="20" />
|
|
|
+ <Icon v-else :type="item.icon" color="white" size="20" />
|
|
|
+ <span class="content-type-label">{{item.label}}</span>
|
|
|
+ <Tooltip transfer theme="light" :content="item.tips" :max-width="248" placement="bottom" offset="-20">
|
|
|
+ <Icon type="ios-alert-outline" color="#1cc0f3" size="20" v-if="item.tips" style="position:absolute;top:-16px;margin-left:5px;" />
|
|
|
+ </Tooltip>
|
|
|
</div>
|
|
|
- <p :style="{color: sizeInfo.total > storageSpace ? 'red' : 'white', fontSize: sizeInfo.total > storageSpace ? '14px' : '12px'}">
|
|
|
- <span>
|
|
|
- {{$t('teachContent.space')}}
|
|
|
- </span>
|
|
|
- <span v-show="sizeLoading">
|
|
|
- {{$t('teachContent.calcing')}}
|
|
|
- </span>
|
|
|
- <span v-show="!sizeLoading">
|
|
|
- {{$jsFn.formatBytes(sizeInfo.total)}}/{{ $jsFn.formatBytes(storageSpace)}}
|
|
|
- </span>
|
|
|
- <span v-if="sizeInfo.total > storageSpace">{{$t('teachContent.blobFull')}}</span>
|
|
|
- </p>
|
|
|
- <div class="percent-detail-box">
|
|
|
- <p class="percent-detail-text" v-if="sizeInfo.res != 0">
|
|
|
- <span class="text-dot storage-res"></span>
|
|
|
- <span>{{$t('teachContent.filterRes')}}</span>
|
|
|
- <span class="text-size">{{$jsFn.formatBytes(sizeInfo.res)}}</span>
|
|
|
- </p>
|
|
|
- <p class="percent-detail-text" v-if="sizeInfo.image != 0">
|
|
|
- <span class="text-dot storage-image"></span>
|
|
|
- <span>{{$t('teachContent.filterPicture')}}</span>
|
|
|
- <span class="text-size">{{$jsFn.formatBytes(sizeInfo.image)}}</span>
|
|
|
- </p>
|
|
|
- <p class="percent-detail-text" v-if="sizeInfo.video != 0">
|
|
|
- <span class="text-dot storage-video"></span>
|
|
|
- <span>{{$t('teachContent.filterVideo')}}</span>
|
|
|
- <span class="text-size">{{$jsFn.formatBytes(sizeInfo.video)}}</span>
|
|
|
- </p>
|
|
|
- <p class="percent-detail-text" v-if="sizeInfo.audio != 0">
|
|
|
- <span class="text-dot storage-audio"></span>
|
|
|
- <span>{{$t('teachContent.filterAudio')}}</span>
|
|
|
- <span class="text-size">{{$jsFn.formatBytes(sizeInfo.audio)}}</span>
|
|
|
- </p>
|
|
|
- <p class="percent-detail-text" v-if="sizeInfo.doc != 0">
|
|
|
- <span class="text-dot storage-doc"></span>
|
|
|
- <span>{{$t('teachContent.filterDoc')}}</span>
|
|
|
- <span class="text-size">{{$jsFn.formatBytes(sizeInfo.doc)}}</span>
|
|
|
- </p>
|
|
|
- <p class="percent-detail-text" v-if="sizeInfo.other != 0">
|
|
|
- <span class="text-dot storage-other"></span>
|
|
|
- <span>{{$t('teachContent.otherType')}}</span>
|
|
|
- <span class="text-size">{{$jsFn.formatBytes(sizeInfo.other)}}</span>
|
|
|
- </p>
|
|
|
- <p class="percent-detail-text" v-if="sizeInfo.data != 0">
|
|
|
- <span class="text-dot storage-data"></span>
|
|
|
- <span>{{$t('teachContent.appData')}}</span>
|
|
|
- <span class="text-size">{{$jsFn.formatBytes(sizeInfo.data)}}</span>
|
|
|
+ <!-- Blob空间计算 -->
|
|
|
+ <div :class="($access.can('admin.*|content-school-upd') || routerScope == 'private') ? 'space-box animated fadeIn fast' : 'space-box animated fadeOut fast'">
|
|
|
+ <div class="percent-box">
|
|
|
+ <span class="percent-item-span storage-full" :style="{ width: '100%' }" v-if="sizeInfo.total > storageSpace"></span>
|
|
|
+ <span class="percent-item-span storage-res" :style='{ width: getPercent(sizeInfo.res) }'></span>
|
|
|
+ <span class="percent-item-span storage-image" :style='{ width: getPercent(sizeInfo.image) }'></span>
|
|
|
+ <span class="percent-item-span storage-video" :style='{ width: getPercent(sizeInfo.video) }'></span>
|
|
|
+ <span class="percent-item-span storage-audio" :style='{ width: getPercent(sizeInfo.audio) }'></span>
|
|
|
+ <span class="percent-item-span storage-doc" :style='{ width: getPercent(sizeInfo.doc) }'></span>
|
|
|
+ <span class="percent-item-span storage-other" :style='{ width: getPercent(sizeInfo.other) }'></span>
|
|
|
+ <span class="percent-item-span storage-data" :style='{ width: getPercent(sizeInfo.data) }'></span>
|
|
|
+ </div>
|
|
|
+ <p :style="{color: sizeInfo.total > storageSpace ? 'red' : 'white', fontSize: sizeInfo.total > storageSpace ? '14px' : '12px'}">
|
|
|
+ <span>
|
|
|
+ {{$t('teachContent.space')}}
|
|
|
+ </span>
|
|
|
+ <span v-show="sizeLoading">
|
|
|
+ {{$t('teachContent.calcing')}}
|
|
|
+ </span>
|
|
|
+ <span v-show="!sizeLoading">
|
|
|
+ {{$jsFn.formatBytes(sizeInfo.total)}}/{{ $jsFn.formatBytes(storageSpace)}}
|
|
|
+ </span>
|
|
|
+ <span v-if="sizeInfo.total > storageSpace">{{$t('teachContent.blobFull')}}</span>
|
|
|
</p>
|
|
|
+ <div class="percent-detail-box">
|
|
|
+ <p class="percent-detail-text" v-if="sizeInfo.res != 0">
|
|
|
+ <span class="text-dot storage-res"></span>
|
|
|
+ <span>{{$t('teachContent.filterRes')}}</span>
|
|
|
+ <span class="text-size">{{$jsFn.formatBytes(sizeInfo.res)}}</span>
|
|
|
+ </p>
|
|
|
+ <p class="percent-detail-text" v-if="sizeInfo.image != 0">
|
|
|
+ <span class="text-dot storage-image"></span>
|
|
|
+ <span>{{$t('teachContent.filterPicture')}}</span>
|
|
|
+ <span class="text-size">{{$jsFn.formatBytes(sizeInfo.image)}}</span>
|
|
|
+ </p>
|
|
|
+ <p class="percent-detail-text" v-if="sizeInfo.video != 0">
|
|
|
+ <span class="text-dot storage-video"></span>
|
|
|
+ <span>{{$t('teachContent.filterVideo')}}</span>
|
|
|
+ <span class="text-size">{{$jsFn.formatBytes(sizeInfo.video)}}</span>
|
|
|
+ </p>
|
|
|
+ <p class="percent-detail-text" v-if="sizeInfo.audio != 0">
|
|
|
+ <span class="text-dot storage-audio"></span>
|
|
|
+ <span>{{$t('teachContent.filterAudio')}}</span>
|
|
|
+ <span class="text-size">{{$jsFn.formatBytes(sizeInfo.audio)}}</span>
|
|
|
+ </p>
|
|
|
+ <p class="percent-detail-text" v-if="sizeInfo.doc != 0">
|
|
|
+ <span class="text-dot storage-doc"></span>
|
|
|
+ <span>{{$t('teachContent.filterDoc')}}</span>
|
|
|
+ <span class="text-size">{{$jsFn.formatBytes(sizeInfo.doc)}}</span>
|
|
|
+ </p>
|
|
|
+ <p class="percent-detail-text" v-if="sizeInfo.other != 0">
|
|
|
+ <span class="text-dot storage-other"></span>
|
|
|
+ <span>{{$t('teachContent.otherType')}}</span>
|
|
|
+ <span class="text-size">{{$jsFn.formatBytes(sizeInfo.other)}}</span>
|
|
|
+ </p>
|
|
|
+ <p class="percent-detail-text" v-if="sizeInfo.data != 0">
|
|
|
+ <span class="text-dot storage-data"></span>
|
|
|
+ <span>{{$t('teachContent.appData')}}</span>
|
|
|
+ <span class="text-size">{{$jsFn.formatBytes(sizeInfo.data)}}</span>
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
+ </vuescroll>
|
|
|
+
|
|
|
</div>
|
|
|
<!--文件表格列表-->
|
|
|
<div class="content-file-list-box">
|
|
@@ -81,12 +84,12 @@
|
|
|
<div class="content-file-filter">
|
|
|
<Input v-model="keyWord" search size="small" :placeholder="$t('teachContent.searchText')" class="key-word-search" @on-change="searchKeyWord" @on-search="searchKeyWord" />
|
|
|
<CheckboxGroup v-model="extFilter" style="display:inline-block;margin-left:38px;margin-top:13px;" @on-change="filterFileByExtension">
|
|
|
- <Checkbox :label="item" v-for="(item ,index) in extensions" :key="index" v-if="activeType !== 0" :class="activeType !== 0 ? 'animated fadeIn' : 'animated fadeOut'">
|
|
|
+ <Checkbox :label="item" v-for="(item ,index) in extensions" :key="index">
|
|
|
<span>{{item}}</span>
|
|
|
</Checkbox>
|
|
|
</CheckboxGroup>
|
|
|
<span v-if="$access.can('admin.*|content-school-upd') || routerScope == 'private'" class="action-btn-wrap" @click="delFileBatch">
|
|
|
- <Icon v-if="$access.can('admin.*|content-school-upd')" type="md-trash" class="toggle-btn-icon" />
|
|
|
+ <Icon type="md-trash" class="toggle-btn-icon" />
|
|
|
{{$t('teachContent.delBatch')}}
|
|
|
</span>
|
|
|
<span v-if="$access.can('admin.*|content-school-upd') || routerScope == 'private'" @click="showUpload" class="action-btn-wrap">
|
|
@@ -102,7 +105,7 @@
|
|
|
<!--文件列表区域-->
|
|
|
<div class="content-file-list dark-iview-loading" id="card-box">
|
|
|
<!--table形式-->
|
|
|
- <div v-if="activeType === 'res' || activeType === 'doc' || activeType === 'other'|| activeType === 'audio' || !showType" class="animated fadeIn dark-iview-table">
|
|
|
+ <div v-if="activeType === 'recent' || activeType === 'res' || activeType === 'doc' || activeType === 'other'|| activeType === 'audio' || !showType" class="animated fadeIn dark-iview-table">
|
|
|
<Table :columns="fileColumns" :data="fileListShow" class="animated fadeIn" @on-selection-change="handleSelect">
|
|
|
<template slot-scope="{ row, index }" slot="size">
|
|
|
<div>
|
|
@@ -155,7 +158,7 @@
|
|
|
<div class="item-tools">
|
|
|
<Icon type="md-download" size="18" color="white" :title="$t('teachContent.tips3')" @click.stop="downloadFile(props.index)" />
|
|
|
<Icon type="md-eye" size="18" color="white" :title="$t('teachContent.tips4')" @click="openPreviewFile(props.index)" />
|
|
|
- <Icon v-if="$access.can('admin.*|content-school-upd')" type="md-trash" size="18" color="white" :title="$t('teachContent.tips7')" @click.stop="delFile(props.value, props.index)" />
|
|
|
+ <Icon v-if="$access.can('admin.*|content-school-upd') || routerScope == 'private'" type="md-trash" size="18" color="white" :title="$t('teachContent.tips7')" @click.stop="delFile(props.value, props.index)" />
|
|
|
<span style="color:white; float:right;margin-right:10px;">{{$jsFn.formatBytes(props.value.size)}}</span>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -192,7 +195,6 @@ import FileSaver from "file-saver";
|
|
|
import JSZip from "jszip";
|
|
|
import elementResizeDetectorMaker from "element-resize-detector"
|
|
|
import VueWaterfall from 'vue-waterfall-easy'
|
|
|
-import { file } from 'jszip';
|
|
|
export default {
|
|
|
components: {
|
|
|
VueWaterfall
|
|
@@ -219,7 +221,7 @@ export default {
|
|
|
previewStatus: false,
|
|
|
storageSpace: 0,
|
|
|
keyWord: '',
|
|
|
- activeType: 'res',
|
|
|
+ activeType: 'recent',
|
|
|
fileList: {},
|
|
|
fileListShow: [],
|
|
|
searchResult: [],
|
|
@@ -323,6 +325,7 @@ export default {
|
|
|
},
|
|
|
//确认上传
|
|
|
async confirmUpd() {
|
|
|
+ this.cacheRecent(this.preUpdFiles)
|
|
|
for (let file of this.preUpdFiles) {
|
|
|
if (!this.fileList[file.type]) {
|
|
|
this.fileList[file.type] = []
|
|
@@ -344,7 +347,7 @@ export default {
|
|
|
n = n.replace(file.name, file.name.slice(0, file.name.lastIndexOf('.'))) + '.png'
|
|
|
file['thum'] = file.url.replace(file.blob, n)
|
|
|
}
|
|
|
- if (this.activeType == file.type) {
|
|
|
+ if (this.activeType == file.type || this.activeType == 'recent') {
|
|
|
this.fileListShow.unshift(file)
|
|
|
this.fileList[file.type].unshift(file)
|
|
|
} else {
|
|
@@ -378,6 +381,40 @@ export default {
|
|
|
}
|
|
|
this.preUpdFiles = []
|
|
|
},
|
|
|
+ //通过localstorage存储最近上传的文件(默认最多20条)
|
|
|
+ cacheRecent(files) {
|
|
|
+ let cacheFiles = []
|
|
|
+ if (this.routerScope == 'private') {
|
|
|
+ cacheFiles = JSON.parse(localStorage.getItem('cachePrivFiles') || '[]')
|
|
|
+ } else {
|
|
|
+ cacheFiles = JSON.parse(localStorage.getItem('cacheSchoolFiles') || '[]')
|
|
|
+ }
|
|
|
+ let f = files.map(item => {
|
|
|
+ return {
|
|
|
+ blob: item.blob,
|
|
|
+ createTime: item.createTime,
|
|
|
+ extension: item.extension,
|
|
|
+ name: item.name,
|
|
|
+ size: item.size,
|
|
|
+ thum: item.thum,
|
|
|
+ type: item.type,
|
|
|
+ url: item.url
|
|
|
+ }
|
|
|
+ })
|
|
|
+ cacheFiles.push(...f)
|
|
|
+ cacheFiles.sort((a, b) => {
|
|
|
+ return b.createTime - a.createTime
|
|
|
+ })
|
|
|
+ let len = cacheFiles.length
|
|
|
+ if (len > 20) {
|
|
|
+ cacheFiles.splice(19, len - 20)
|
|
|
+ }
|
|
|
+ if (this.routerScope == 'private') {
|
|
|
+ localStorage.setItem('cachePrivFiles', JSON.stringify(cacheFiles))
|
|
|
+ } else {
|
|
|
+ localStorage.setItem('cacheSchoolFiles', JSON.stringify(cacheFiles))
|
|
|
+ }
|
|
|
+ },
|
|
|
//计算空间占比
|
|
|
getPercent(size) {
|
|
|
if (this.sizeInfo.total > this.storageSpace) {
|
|
@@ -464,10 +501,17 @@ export default {
|
|
|
}
|
|
|
]
|
|
|
this.contentTypeList = [
|
|
|
+ {
|
|
|
+ label: '最近',
|
|
|
+ type: 'recent',
|
|
|
+ icon: 'md-time',
|
|
|
+ tips: '仅本地临时缓存最近上传的资源,最多保存20条。退出账号或者更换电脑记录将会清空。'
|
|
|
+ },
|
|
|
{
|
|
|
label: this.$t('teachContent.filterRes'),
|
|
|
type: 'res',
|
|
|
- icon: 'iconfont icon-htex'
|
|
|
+ icon: 'iconfont icon-htex',
|
|
|
+ tips: this.$t('teachContent.resTips')
|
|
|
},
|
|
|
{
|
|
|
label: this.$t('teachContent.filterPicture'),
|
|
@@ -543,7 +587,7 @@ export default {
|
|
|
this.urlString = sasRes.url
|
|
|
this.containerName = sasRes.name
|
|
|
this.containerClient = new BlobTool(this.urlString, this.containerName, this.sasString, scope)
|
|
|
- this.findFileList()
|
|
|
+ // this.findFileList()
|
|
|
} else {
|
|
|
this.$Message.error(this.$t('teachContent.authErr'))
|
|
|
}
|
|
@@ -834,18 +878,17 @@ export default {
|
|
|
}
|
|
|
this.fileList[this.activeType] = res.blobList
|
|
|
this.fileListShow = this._.cloneDeep(this.fileList[this.activeType])
|
|
|
- setTimeout(() => {
|
|
|
- this.isLoading = false
|
|
|
- }, 500)
|
|
|
this.searchBefore = this.fileList[this.activeType]
|
|
|
this.getFilesExtension()
|
|
|
},
|
|
|
(err) => {
|
|
|
- setTimeout(() => {
|
|
|
- this.isLoading = false
|
|
|
- }, 500)
|
|
|
+
|
|
|
}
|
|
|
- )
|
|
|
+ ).finally(() => {
|
|
|
+ setTimeout(() => {
|
|
|
+ this.isLoading = false
|
|
|
+ }, 500)
|
|
|
+ })
|
|
|
}
|
|
|
},
|
|
|
|
|
@@ -874,7 +917,21 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
-
|
|
|
+ //获取本地缓存最近上传数据
|
|
|
+ getCacheFiles() {
|
|
|
+ let files = []
|
|
|
+ if (this.routerScope == 'private') {
|
|
|
+ files = JSON.parse(localStorage.getItem('cachePrivFiles') || '[]')
|
|
|
+ } else {
|
|
|
+ files = JSON.parse(localStorage.getItem('cacheSchoolFiles') || '[]')
|
|
|
+ }
|
|
|
+ files.forEach(item => {
|
|
|
+ item.url = item.url + this.sasString
|
|
|
+ })
|
|
|
+ this.fileListShow = files
|
|
|
+ this.searchBefore = this.fileListShow
|
|
|
+ this.extensions = []
|
|
|
+ },
|
|
|
/**
|
|
|
* 根据文件类型筛选
|
|
|
* @param index
|
|
@@ -883,6 +940,11 @@ export default {
|
|
|
this.extFilter = []
|
|
|
this.selections.length = 0
|
|
|
this.activeType = this.contentTypeList[index].type
|
|
|
+ //最近上传文件读取本地storage
|
|
|
+ if (this.activeType == 'recent') {
|
|
|
+ this.getCacheFiles()
|
|
|
+ return
|
|
|
+ }
|
|
|
if (this.isFirst[this.activeType]) {
|
|
|
this.fileListShow.length = 0
|
|
|
this.findFileList()
|
|
@@ -948,6 +1010,7 @@ export default {
|
|
|
).finally(() => {
|
|
|
this.sizeLoading = false
|
|
|
})
|
|
|
+ this.getCacheFiles()
|
|
|
},
|
|
|
watch: {
|
|
|
$route: {
|
|
@@ -960,7 +1023,7 @@ export default {
|
|
|
this.routerScope = 'private'
|
|
|
this.storageSpace = this.$GLOBAL.PRIVATE_SPACE
|
|
|
}
|
|
|
- this.activeType = 'res'
|
|
|
+ // this.activeType = 'recent'
|
|
|
this.getSasStr()
|
|
|
},
|
|
|
immediate: true
|