301 lines
6.9 KiB
Vue
301 lines
6.9 KiB
Vue
<template>
|
|
<view class="pre-box">
|
|
<template v-if="fileList.length > 0 ">
|
|
<view class="pre-item" v-for="(item, index) in fileList" :key="index">
|
|
<template v-if="item.progress === 100">
|
|
<image
|
|
v-if="isImage(item.url)"
|
|
class="pre-item-content"
|
|
:src="item.url"
|
|
mode="aspectFill"
|
|
@tap="previewImage(item)"
|
|
></image>
|
|
<video
|
|
v-if="isVideo(item.url)"
|
|
class="pre-item-content"
|
|
:src="item.url"
|
|
muted
|
|
></video>
|
|
</template>
|
|
<view v-if="item.progress === 0">上传中...</view>
|
|
<view v-if="item.progress === -1" @click="uploadAction(item)">上传失败<br/>点击重试</view>
|
|
<view class="u-delete-icon" @tap="deleteImage(index)">
|
|
<u-icon name="close" size="20" color="#ffffff"></u-icon>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<!-- 上传按钮 -->
|
|
<view @tap="chooseVideoImage2" class="pre-item upload-btn" v-if="fileList.length < limit">
|
|
<view style="display: flex; justify-content: center; width: 100%; height: 100%">
|
|
<u-icon name="photo" size="48" color="#666666"></u-icon>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import {uploadFile} from "@/api/common";
|
|
import {getMediaType, IMAGE, VIDEO} from "@/utils/media";
|
|
import {getRealUrl} from "@/utils";
|
|
|
|
var sourceType = [
|
|
['camera'],
|
|
['album'],
|
|
['camera', 'album']
|
|
]
|
|
|
|
export default {
|
|
name: "MediaInput",
|
|
props: {
|
|
value: {
|
|
type: String,
|
|
default: ""
|
|
},
|
|
limit: {
|
|
type: Number,
|
|
default: 9
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
fileList: [], // 文件列表
|
|
sourceTypeIndex: 2,
|
|
sourceType: ['拍摄', '相册', '拍摄或相册'],
|
|
cameraList: [{
|
|
value: 'back',
|
|
name: '后置摄像头',
|
|
checked: 'true'
|
|
}, {
|
|
value: 'front',
|
|
name: '前置摄像头'
|
|
}],
|
|
cameraIndex: 0,
|
|
};
|
|
},
|
|
computed: {
|
|
isImage() {
|
|
return (url) => {
|
|
return getMediaType(url) === IMAGE;
|
|
}
|
|
},
|
|
isVideo() {
|
|
return (url) => {
|
|
return getMediaType(url) === VIDEO;
|
|
}
|
|
},
|
|
|
|
},
|
|
watch: {
|
|
value: {
|
|
handler(val) {
|
|
if (val) {
|
|
// 首先将值转为数组
|
|
let list = Array.isArray(val) ? val : this.value.split(',');
|
|
this.fileList = list.map(item => {
|
|
return {
|
|
url: item,
|
|
progress: 100
|
|
}
|
|
})
|
|
} else {
|
|
this.fileList = [];
|
|
}
|
|
},
|
|
deep: true,
|
|
immediate: true
|
|
}
|
|
},
|
|
onShow() {
|
|
this.sourceTypeIndex = 2;
|
|
this.sourceType = ['拍摄', '相册', '拍摄或相册'];
|
|
},
|
|
methods: {
|
|
getFileSplits() {
|
|
return this.fileList.map(item => getRealUrl(item.url)).join(",");
|
|
},
|
|
// 点击上传图片或视频
|
|
chooseVideoImage() {
|
|
uni.showActionSheet({
|
|
title: '选择上传类型',
|
|
itemList: ['图片', '视频'],
|
|
success: res => {
|
|
if (res.tapIndex == 0) {
|
|
this.chooseImages(); //选择上传图片
|
|
} else {
|
|
this.chooseVideo(); //选择上传视频
|
|
}
|
|
}
|
|
});
|
|
},
|
|
chooseVideoImage2() {
|
|
uni.chooseMedia({
|
|
count: 50,
|
|
mediaType: ['mix'],
|
|
sourceType: ['album', 'camera'],
|
|
maxDuration: 60,
|
|
camera: 'back',
|
|
success: res => {
|
|
console.log("chooseMedia", res);
|
|
res.tempFiles.forEach(item => {
|
|
this.fileList.push({
|
|
url: item.tempFilePath,
|
|
progress: 0
|
|
})
|
|
})
|
|
this.startUpload();
|
|
}
|
|
})
|
|
},
|
|
// 上传图片
|
|
chooseImages() {
|
|
uni.chooseImage({
|
|
count: 5, //总限制5张
|
|
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
|
|
sourceType: ['album', 'camera'], //从相册选择
|
|
success: res => {
|
|
console.log("res", res);
|
|
res.tempFilePaths.forEach(url => {
|
|
this.fileList.push({
|
|
url: url,
|
|
progress: 0
|
|
})
|
|
})
|
|
console.log("fileList", this.fileList);
|
|
this.startUpload();
|
|
},
|
|
})
|
|
},
|
|
// 上传视频
|
|
chooseVideo() {
|
|
uni.chooseVideo({
|
|
maxDuration: 60, //拍摄视频最长拍摄时间,单位秒。最长支持 60 秒
|
|
count: 1,
|
|
camera: this.cameraList[this.cameraIndex].value, //'front'、'back',默认'back'
|
|
sourceType: sourceType[this.sourceTypeIndex],
|
|
success: res => {
|
|
this.fileList.push({
|
|
url: res.tempFilePath,
|
|
progress: 0
|
|
})
|
|
this.startUpload();
|
|
}
|
|
})
|
|
},
|
|
// 开始上传
|
|
startUpload() {
|
|
this.fileList.forEach((item) => {
|
|
if (item.progress === 0) {
|
|
this.uploadAction(item)
|
|
}
|
|
})
|
|
},
|
|
// 上传接口
|
|
uploadAction(file) {
|
|
let timeout = 10000;
|
|
if (this.isVideo(file.url)) {
|
|
timeout = 60000;
|
|
}
|
|
uploadFile(file.url, timeout).then(res => {
|
|
if (res.code === 200) {
|
|
file.url = res.url;
|
|
file.progress = 100;
|
|
} else {
|
|
file.progress = -1;
|
|
}
|
|
}).catch((e) => {
|
|
file.progress = -1;
|
|
})
|
|
},
|
|
// 预览图片
|
|
previewImage(e) {
|
|
console.log('预览图片', e)
|
|
var current = e;
|
|
uni.previewImage({
|
|
current: current,
|
|
urls: this.fileList
|
|
});
|
|
},
|
|
// 删除文件
|
|
deleteImage(index) {
|
|
// if( this.fileList.some(item => item.progress === 0) ) {
|
|
// return uni.showToast({
|
|
// title: '请等待文件上传完成',
|
|
// icon: 'none'
|
|
// })
|
|
// }
|
|
uni.showModal({
|
|
title: '提示',
|
|
content: '是否要删除该图片',
|
|
success: res => {
|
|
if (res.confirm) {
|
|
this.fileList.splice(index, 1);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.pre-box {
|
|
position: relative;
|
|
width: 100%;
|
|
height: fit-content;
|
|
padding: 8rpx;
|
|
display: flex;
|
|
justify-content: flex-start;
|
|
flex-wrap: wrap;
|
|
.pre-item {
|
|
position: relative;
|
|
width: 33%;
|
|
height: auto;
|
|
padding: 8rpx;
|
|
aspect-ratio: 1/1;
|
|
.pre-item-content {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
.upload-btn {
|
|
border-radius: 16rpx;
|
|
border: 1px dashed #CCCCCC;
|
|
}
|
|
}
|
|
|
|
.u-progress {
|
|
position: absolute;
|
|
bottom: 10rpx;
|
|
left: 8rpx;
|
|
right: 8rpx;
|
|
z-index: 9;
|
|
width: auto;
|
|
}
|
|
|
|
.u-delete-icon {
|
|
position: absolute;
|
|
top: 4rpx;
|
|
right: 4rpx;
|
|
z-index: 10;
|
|
background-color: #CCCCCC;
|
|
border-radius: 100rpx;
|
|
width: 36rpx;
|
|
height: 36rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.u-progress {
|
|
position: absolute;
|
|
bottom: 10rpx;
|
|
left: 8rpx;
|
|
right: 8rpx;
|
|
z-index: 9;
|
|
width: auto;
|
|
}
|
|
|
|
|
|
</style>
|