最近在做小程序,最后想试试新不同的技术,所以选择了用uniapp做小程序。
要求实现多张图片的上传 ,可以限制图片上传的数量,图片预览,多次使用对图片的上传顺序排序
<template>
<view>
<view class="upload">
<!-- 对视频或者图片进行循环 -->
<block v-for="(upload,index) in uploads" :key="index">
<view class="uplode-file">
<!-- 判断是图片还是视频 如果是视频通过 image 进行展示 -->
<image v-if="types == 'image'" class="uploade-img" :src="upload" :data-src="upload" @tap="previewImage"></image>
<!-- 用于取消的图片 -->
<image v-if="types == 'image'" class="clear-one-icon" :src="clearIcon" @tap="delImage(index)"></image>
<!-- 如果是视频通过 video进行展示 在视频标签上面添加个图片(删除图片用于取消视频) -->
<video v-if="types == 'video'" class="uploade-img" :src="upload" controls>
<cover-image v-if="types == 'video'" class="clear-one-icon" :src="clearIcon" @tap="delImage(index)"></cover-image>
</video>
</view>
</block>
<!-- 这里是对于没有图片上传之前的样式的展示 如果图片视频的上传的数量大于等于 设定的图片上传的数量 就对不在展示 该样式 这样的话 就不能继续在 上传图片了-->
<view v-if="uploads.length < uploadCount" :class="uploadIcon ? 'uploader-icon' : 'uploader-input-box'">
<view v-if="!uploadIcon" class="uploader-input" @tap="chooseUploads"></view>
<image v-else class="image-cion" :src="uploadIcon" @tap="chooseUploads"></image>
<view style="height: 40upx; height: 25upx;">
</view>
<!-- 这里是对于上传图片的提示 -->
<p class="ziliao" v-for="(item,index) in text" :key="index"> {{item}}</p>
</view>
</view>
<!-- 提交上传 -->
<button type="primary" v-if="types == 'image'" @tap="upload" >上传</button>
</view>
</template>
<script>
export default{
// props 接受传递过来的值
props: {
// 上传的图片的提示
text: {
type: Array,
default: function() {
return []
}
},
// 用于判断上传的是图片还是视频
types: {
type: String,
default: 'image'
},
// 图片上传的路径
dataList: {
type: Array,
default: function() {
return []
}
},
// 图标 用于去除已经选中的图片
clearIcon: {
type: String,
default: 'http://img1.imgtn.bdimg.com/it/u=451604666,2295832001&fm=26&gp=0.jpg'
},
// 上传的图片的样式 比如说是个相机 还是加号
uploadIcon: {
type: String,
default: ''
},
// 需要将图片上传到服务器的 地址
uploadUrl: {
type: String,
default: ''
},
// 删除图片的地址
deleteUrl: {
type: String,
default: ''
},
// 设置上传图片或视频的数量
uploadCount: {
type: Number,
default: 1
},
//上传图片大小 默认3M
upload_max: {
type: Number,
default: 3
},
disable:{
type: Boolean,
default: true,
}
},
data(){
return {
//上传的图片地址
uploadImages: [],
//展示的图片地址
uploads: [],
// 超出限制数组
exceeded_list: [],
}
},
mounted(){
// 对上传图片做个判断
this.uploads = this.dataList
},
methods:{
previewImage (e) {
var current = e.target.dataset.src
uni.previewImage({
current: current,
urls: this.dataList
})
},
chooseUploads(){
switch (this.types){
case 'image':
uni.chooseImage({
count: this.uploadCount - this.uploads.length, //默认9
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], //从相册选择
success: (res) => {
for(let i = 0; i< res.tempFiles.length; i++){
if(Math.ceil(res.tempFiles[i].size / 1024) < this.upload_max * 1024){
this.uploads.push(res.tempFiles[i].path)
this.uploadImages.push(res.tempFiles[i].path)
}else {
this.exceeded_list.push(i === 0 ? 1 : i + 1);
uni.showModal({
title: '提示',
content: `第${[...new Set(this.exceeded_list)].join(',')}张图片超出限制${this.upload_max}MB,已过滤`
});
}
}
},
fail: (err) => {
uni.showModal({
// content: JSON.stringify(err)
content: '选择被取消'
});
}
});
break;
case 'video' :
uni.chooseVideo({
sourceType: ['camera', 'album'],
success: (res) => {
if(Math.ceil(res.size / 1024) < this.upload_max * 1024){
this.uploads.push(res.tempFilePath)
uni.uploadFile({
url: this.uploadUrl, //仅为示例,非真实的接口地址
filePath: res.tempFilePath,
name: 'file',
//请求参数
formData: {
'user': 'test'
},
success: (uploadFileRes) => {
this.$emit('successVideo',uploadFileRes)
}
});
}else {
uni.showModal({
title: '提示',
content: `第${[...new Set(this.exceeded_list)].join(',')}张视频超出限制${this.upload_max}MB,已过滤`
});
}
},
fail: (err) => {
uni.showModal({
// content: JSON.stringify(err)
content: '确认取消?'
});
}
});
break;
}
},
delImage(index){
//第一个是判断app或者h5的 第二个是判断小程序的
if(this.uploads[index].substring(0,4) !== 'http' || this.uploads[index].substring(0,11) == 'http://tmp/'){
this.uploads.splice(index,1)
return;
};
if(!this.deleteUrl) {
uni.showModal({
content: '请填写删除接口'
});
return;
};
uni.request({
url: this.deleteUrl,
method: 'DELETE',
data: {
image: this.dataList[index]
},
success: res => {
console.log(123456);
if(res.data.status == 1) {
uni.showToast({
title: '删除成功'
})
this.uploads.splice(index,1)
}
},
});
},
upload(){
var _this = this
var j = 0
if(!this.disable){
uni.showModal({
content: '请先上传上面的哟'
});
return;
}
if(!this.uploadUrl) {
uni.showModal({
content: '请填写上传接口'
});
return;
};
if(this.uploadImages.length < 1){
uni.showModal({
content: '请选择图片'
});
return;
}
if(this.uploadImages.length < this.uploadCount){
uni.showModal({
content: '请确认上传的数量为' + this.uploadCount + '张'
});
return;
}
for (let i of this.uploadImages) {
uni.uploadFile({
url: this.uploadUrl, //仅为示例,非真实的接口地址
filePath: i,
name: 'images[]',
//请求参数
formData: {
'user': 'test'
},
success: (uploadFileRes) => {
this.$emit('successImage',uploadFileRes)
j++
console.log(j)
if( j == _this.uploadCount){
this.$emit('successImages',true)
}
}
});
}
}
}
}
</script>
<style scoped>
.ziliao{
margin-top: 15upx;
text-align: center;
font-family: MicrosoftYaHei;
font-size: 20upx;
font-weight: normal;
font-stretch: normal;
line-height: 32upx;
letter-spacing: 0upx;
color: #c8c8c8;
}
button{
background-color: #f05a23;
width: 95%;
}
.upload {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.uplode-file {
margin: 10upx;
width: 210upx;
height: 210upx;
position: relative;
}
.uploade-img {
display: block;
width: 210upx;
height: 210upx;
}
.clear-one{
position: absolute;
top: -10rpx;
right: 0;
}
.clear-one-icon{
position: absolute;
width: 20px;
height: 20px;
top: 0;
right: 0;
z-index: 9;
}
.uploader-input-box {
position: relative;
margin:10upx;
width: 208upx;
height: 208upx;
border: 2upx solid #D9D9D9;
}
.uploader-input-box:before,
.uploader-input-box:after {
content: " ";
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
background-color: #D9D9D9;
}
.uploader-input-box:before {
width: 4upx;
height: 79upx;
}
.uploader-input-box:after {
width: 79upx;
height: 4upx;
}
.uploader-input-box:active {
border-color: #999999;
}
.uploader-input-box:active:before,
.uploader-input-box:active:after {
background-color: #999999;
}
.uploader-input {
position: absolute;
z-index: 1;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
}
.uploader-icon{
position: relative;
margin:10upx;
width: 208upx;
height: 208upx;
}
.uploader-icon .image-cion{
width: 100%;
height: 100%;
}
</style>
使用方式:
<easyupload
:text="text" :dataList="imageList"
uploadUrl="http://sunshine.createnetwork.cn/api/uploadimage"
:types="category"
deleteUrl='http://sunshine.createnetwork.cn/api/uploadimage'
:uploadCount="2"
disable = true
@successImage="successImage"
@successVideo="successvideo"
@successImages="successImages"
class="sxzl"
></easyupload>
<easyupload
:text="text1"
:dataList="imageList"
uploadUrl="http://sunshine.createnetwork.cn/api/uploadimage"
:types="category"
deleteUrl='http://sunshine.createnetwork.cn/api/uploadimage'
:uploadCount="2"
:disable= 'Drivinglicense'
@successImage="successImage"
@successVideo="successvideo"
@successImages="successImages"
class="sxzl"
></easyupload>
<script>
// 导入注册组件
import easyupload from "@/common/easy-upload.vue"
export default {
components:{
easyupload
},
data() {
return {
tx_details:'',
Drivinglicense: false,
data:{
phone:'',
plate_number:'',
type_id:'',
id_card:[],
driving_card:[],
name:''
},
news:'',
right_select_num:0,
text:["身份证正面","身份证反面"],
text1:["行驶证正页","行驶证副页"],
imageList: [],
category: 'image',
car1:"请选择车品牌",
};
},
watch:{
// 对数据进行深度监听 用于设置使用组件的顺序 (多次使用组件并且需要考虑顺序的情况下使用)
'data.id_card':{
handler(newName, oldName) {
// console.log('data.id_card', chnsg.length,oldName);
( oldName.length >= 2) ? (this.Drivinglicense = true) : (this.Drivinglicense = false)
console.log(this.Drivinglicense);
},
immediate: true,
deep: true,
}
},
methods:{
successImages(e){
if(e){
uni.showModal({
content : '图片上传成功'
})
}
},
successImage(e){
console.log(JSON.parse(e.data).data)
this.Drivinglicense ?this.data.driving_card.push(JSON.parse(e.data).data[0]) : this.data.id_card.push(JSON.parse(e.data).data[0])
console.log(this.data.id_card,this.data.driving_card);
},
successvideo(e){
console.log(e)
},
}
}
</script>
使用效果:
这是图片预览效果:
对图片上传数量的限制
图片上传成功提示
取消选择选择图片提示
对于图片上传顺序的限制
没有选择图片的提示
选择图片后效果