Commit 0519d9c2 by 陈超

A

parent e2110869
<template> <template>
<div class="gallery"> <div class="uploader_container">
<div v-for="(file, index) in fileList" :key="index" class="image_holder" :style="picStyle">
<el-image v-loading="file.status == 'ready'" v-if="showImage(file)" class="image_content" :src="file.url" <div v-for="(file, index) in fileList" :key="index" class="image_holder" :style="picStyle">
fit="cover"></el-image> <el-image v-loading="file.status == 'ready'" v-if="showImage(file)" class="image_content" :src="file.url"
<div v-loading="file.status == 'ready'" class="video_holder" v-if="showVideo(file)"> fit="cover"></el-image>
<el-image src="/images/zanting_b.png" :style="playStyle" /> <div v-loading="file.status == 'ready'" class="video_holder" v-if="showVideo(file)">
</div> <el-image src="/images/zanting_b.png" :style="playStyle" />
<div class="image_mask"> </div>
<div class="layout_h_c"> <div class="image_mask">
<el-button v-if="showDelete(file)" type="text" icon="el-icon-delete" <div class="layout_h_c">
class="dustbin" @click="onDeleteImage(index)"></el-button> <el-button v-if="showDelete(file)" type="text" icon="el-icon-delete"
<el-button v-if="showPlay(file)" type="text" icon="el-icon-video-play" class="dustbin" @click="onFileRemove(index)"></el-button>
class="dustbin" @click="onPlayVideo(index)"></el-button> <el-button v-if="showPlay(file)" type="text" icon="el-icon-video-play"
</div> class="dustbin" @click="onPlayVideo(index)"></el-button>
</div> </div>
</div> </div>
<el-upload v-if="showTrigger" class="upload-demo" multiple :action="actionUrl" :show-file-list="false" </div>
:http-request="onUpload" :auto-upload="true" :on-success="onSuccessUpload" :on-exceed="onExceed"
:on-change="onFileChanged" :limit="max" :style="picStyle" :file-list="fileList"> <div class="input_container" v-if="showTrigger" :style="picStyle">
<div class="plus_loader" slot="trigger" :style="picStyle"> <input class="input_el" :accept="accept" :multiple="multiple" :max="maxSelected" type="file" @change.prevent.stop="onChange" />
<i class="el-icon-plus"></i> <div class="plus_loader" slot="trigger" :style="picStyle">
</div> <i class="el-icon-plus"></i>
</el-upload> </div>
</div>
<core-player :show="showPlayer" :url="nowUrl" @close="showPlayer = false" /> <core-player :show="showPlayer" :url="nowUrl" @close="showPlayer = false" />
<span v-if="tips.default" style="color:#2790e0;white-space: nowrap;">{{tips.content}}</span> <span v-if="tips.default" style="color:#2790e0;white-space: nowrap;">{{tips.content}}</span>
</div>
</div>
</template> </template>
<script> <script>
export default {
components: { export default {
'core-player': () => import('@/components/player.vue') props: {
},
props: {
tips:{ tips:{
type: Object, type: Object,
default: () => { default: () => {
...@@ -45,53 +45,56 @@ ...@@ -45,53 +45,56 @@
} }
} }
}, },
max: { max: {
type: Number, type: Number,
default: 1 default: 1
}, },
size: { size: {
type: Object, type: Object,
default: () => { default: () => {
return { return {
width: "120px", width: "120px",
height: "160px" height: "160px"
} }
} }
}, },
playSize: { playSize: {
type: Object, type: Object,
default: () => { default: () => {
return { return {
width: '60px', width: '60px',
height: '60px' height: '60px'
} }
} }
}, },
urls: { urls: {
type: String, type: String,
default: "" default: ""
}, },
lazyList: { lazyList: {
type: String, type: String,
default: "" default: ""
}, },
image: { image: {
type: Boolean, type: Boolean,
default: true default: true
}, },
video: { video: {
type: Boolean, type: Boolean,
default: false default: false
} }
},
components: {
'core-player': () => import('@/components/player.vue')
}, },
data() { data() {
return { return {
nowUrl: '', nowUrl: '',
showPlayer: false, showPlayer: false,
lazyLoaded: false, lazyLoaded: false,
fileList: [], fileList: []
} }
}, },
watch: { watch: {
lazyList(n, o) { lazyList(n, o) {
if(n && n.length > 0 && !this.lazyLoaded) { if(n && n.length > 0 && !this.lazyLoaded) {
...@@ -113,60 +116,113 @@ ...@@ -113,60 +116,113 @@
this.lazyLoad(n) this.lazyLoad(n)
} }
}, },
methods: { computed: {
lazyLoad(n) { picStyle() {
this.lazyLoaded = true let size = this.size
this.delayInit(n) return {
width: size.width,
height: size.height,
marginRight: "10px"
}
},
playStyle() {
let size = this.playSize
return {
width: size.width,
height: size.height
}
},
showTrigger() {
return this.fileList.length < this.max
}, },
onUpload(req) { //是否显示图片
let f = req.file showImage() {
let bucket = "" return f => {
if (f.type.startsWith('image') && this.image) { return (f.type && f.type.startsWith('image')) || this.isImage(f.url)
bucket = 'images'
} else if (f.type.startsWith('video') && this.video) {
bucket = 'videos'
} else {
req.onError('不支持的文件格式')
return
} }
this.$oss.upload(bucket, f)
.then(r => {
req.onSuccess(r)
})
.catch(e => {
req.onError(e)
})
}, },
onSuccessUpload(r, f, l) { //是否显示视频
f.url = r.url showVideo() {
return f => {
return (f.type && f.type.startsWith('video')) || this.isVideo(f.url)
}
}, },
onExceed(f, l) { //是否显示删除按钮
this.$message({ showDelete() {
message: '文件数量不能超过' + this.max + "个", return f => {
type: 'warning' return f.status == undefined || f.status == 'success'
}) }
}, },
onFileChanged(f, l) { //显示播放按钮
if (f.status == 'ready') { showPlay() {
f.url = window.URL.createObjectURL(f.raw) return f => {
return (f.status == undefined || f.status == 'success') && this.isVideo(f.url)
} }
if(f.status == 'success') { },
this.fileList = l validCount() {
this.$emit('change', this.getList()) return this.fileList.length
},
//原生属性
multiple() {
return this.max > 1
},
maxSelected() {
return Math.max(0, this.max - this.fileList.length)
},
accept() {
let str = []
if (this.image) {
str.push("image/*")
}
if (this.video) {
str.push("video/*")
}
return str.join(',')
}
},
methods: {
urlList() {
let array = []
for(let value of this.fileList) {
if(value.url) {
array.push(value.url)
}
} }
return array
}, },
//删除文件 isImage(str) {
onDeleteImage(index) { if(str == undefined) {
this.fileList.splice(index, 1) return false
}
let sufix = ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp', 'psd', 'svg', 'tiff', 'ico']
for (let i = 0; i < sufix.length; i++) {
let sf = sufix[i]
if (str.endsWith(sf)) {
return true
}
}
return false
}, },
//播放视频 isVideo(str) {
onPlayVideo(index) { if(str == undefined) {
let f = this.fileList[index] return false
if(f.url) {
this.showPlayer = true
this.nowUrl = f.url
} }
let sufix = ['mp4', 'avi', 'wmv', 'asf', 'rmvb', 'mov', 'm4v', 'mkv', 'flv', 'vob', 'dat', 'rm']
for (let i = 0; i < sufix.length; i++) {
let sf = sufix[i]
if (str.endsWith(sf)) {
return true
}
}
return false
},
//对外接口 start
lazyLoad(n) {
this.lazyLoaded = true
this.delayInit(n)
}, },
delayInit(urls) { delayInit(urls) {
this.$nextTick(() => { this.$nextTick(() => {
this.fileList = urls.split(",").map(url => { this.fileList = urls.split(",").map(url => {
...@@ -177,14 +233,17 @@ ...@@ -177,14 +233,17 @@
}) })
}) })
}, },
initList(list) { initList(list) {
this.fileList = list this.fileList = list
}, },
pushList(list) { pushList(list) {
this.$nextTick(() => { this.$nextTick(() => {
this.fileList = this.fileList.concat(list) this.fileList = this.fileList.concat(list)
}) })
}, },
getList() { getList() {
return this.fileList.filter(r => { return this.fileList.filter(r => {
return r.status == 'success' || r.url return r.status == 'success' || r.url
...@@ -192,158 +251,183 @@ ...@@ -192,158 +251,183 @@
return r.url return r.url
}) })
}, },
isImage(str) {
let sufix = ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp', 'psd', 'svg', 'tiff', 'ico'] //对外接口 end
for (let i = 0; i < sufix.length; i++) { fileUpload(value, file) {
let sf = sufix[i] if(value && value.status == 'ready' && file) {
if (str.endsWith(sf)) { let bucket = ""
return true if (file.type.startsWith('image') && this.image) {
} bucket = 'images'
} } else if (file.type.startsWith('video') && this.video) {
return false bucket = 'videos'
}, } else {
isVideo(str) { this.onFileUploadError(value)
let sufix = ['mp4', 'avi', 'wmv', 'asf', 'rmvb', 'mov', 'm4v', 'mkv', 'flv', 'vob', 'dat', 'rm'] return
for (let i = 0; i < sufix.length; i++) {
let sf = sufix[i]
if (str.endsWith(sf)) {
return true
} }
} this.$oss.upload(bucket, file)
return false .then(r => {
} this.onFileUploadSuccess(value, r)
}, })
computed: { .catch(e => {
actionUrl() { this.onFileUploadError(value)
return "" })
}, }
showHolder() { },
return this.fileList.length < this.max onFileRemove(index) {
this.fileList.splice(index, 1)
this.$emit('change', this.urlList())
}, },
picStyle() { onFileUploadSuccess(value, r) {
let size = this.size value.status = 'success'
return { value.url = r.url
width: size.width, this.$emit('change', this.urlList())
height: size.height,
marginRight: "10px"
}
}, },
playStyle() { onFileUploadError(value) {
let size = this.playSize let index = -1
return { for(let i = 0; i < this.fileList.length; i++) {
width: size.width, let v = this.fileList[i]
height: size.height if(v === value) {
} index = i
}, break
showTrigger() { }
return this.fileList.length < this.max
},
//是否显示图片
showImage() {
return f => {
return (f.type != null && f.type.startsWith('image')) || this.isImage(f.url)
} }
}, if(i >= 0) {
//是否显示视频 this.fileList.splice(index, 1)
showVideo() { this.$emit('change', this.urlList())
return f => {
return (f.type != null && f.type.startsWith('video')) || this.isVideo(f.url)
} }
}, },
//是否显示删除按钮
showDelete() { onPlayVideo(index) {
return f => { let f = this.fileList[index]
return f.status == undefined || f.status == 'success' if(f.url) {
this.showPlayer = true
this.nowUrl = f.url
} }
}, },
//显示播放按钮
showPlay() { onChange(r) {
return f => { let files = event.target.files
return (f.status == undefined || f.status == 'success') && this.isVideo(f.url) if(files && files.length > 0) {
} let pick = Math.min(this.maxSelected, files.length)
} for(let i = 0; i < pick; i++) {
} let f = files[i]
} let value = {
name: f.name,
type: f.type,
file: f,
status: 'ready'
}
this.fileList.push(value)
this.fileUpload(value, f)
}
}
}
}
}
</script> </script>
<style scoped> <style scoped>
.plus_loader { .uploader_container {
height: 100%; display: flex;
width: 100%; flex-direction: row;
display: flex; flex-wrap: wrap;
align-items: center; }
justify-content: center;
border-color: #409EFF; .input_container {
border: 1px dashed #d9d9d9; position: relative;
border-radius: 6px; }
}
.input_el:hover, .input_el:focus, .input_el:active {
cursor: pointer;
}
.input_el {
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
opacity: 0;
-ms-filter: 'alpha(opacity=0)';
}
.plus_loader {
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
border-color: #409EFF;
border: 1px dashed #d9d9d9;
border-radius: 6px;
}
.plus_loader:hover { .plus_loader:hover {
border-color: #409EFF; border-color: #409EFF;
} }
.gallery { .gallery {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
flex-wrap: wrap; flex-wrap: wrap;
} }
.dustbin { .dustbin {
height: 32px; height: 32px;
width: 32px; width: 32px;
align-self: center; align-self: center;
} }
.image_holder { .image_holder {
position: relative; position: relative;
border-color: #409EFF; border-color: #409EFF;
border: 1px dashed #d9d9d9; border: 1px dashed #d9d9d9;
border-radius: 6px; border-radius: 6px;
margin-bottom: 6px; margin-bottom: 6px;
overflow: hidden; overflow: hidden;
} }
.image_content { .image_content {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
.video_holder { .video_holder {
width: 100%; width: 100%;
height: 100%; height: 100%;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
background: black; background: black;
} }
.image_mask { .image_mask {
width: 100%; width: 100%;
height: 100%; height: 100%;
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
background: rgba(0, 0, 0, 0.65); background: rgba(0, 0, 0, 0.65);
opacity: 0; opacity: 0;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
} }
.image_mask:hover { .image_mask:hover {
animation: fade 0.3s linear; animation: fade 0.3s linear;
animation-fill-mode: forwards; animation-fill-mode: forwards;
} }
@keyframes fade { @keyframes fade {
0% { 0% {
opacity: 0; opacity: 0;
} }
50% { 50% {
opacity: 0.5; opacity: 0.5;
} }
100% { 100% {
opacity: 1; opacity: 1;
} }
} }
</style> </style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment