特点:
- 支持拍照和本地选择
- 可以限制最多上传几个
- 支持删除
- 实时同步选择个数,并在达到限制是隐藏上传入口
- 自适应布局,自动换行
先看效果
上面0/4是我没及时更新最新图片,其实是自动计算的
- 使用方式:简单粗暴直接放在外层
<view class="evidence">
<view class="title">证据截图</view>
<uploadImage bind:change="updateEvidenceImageList" limitCount="{{4}}"/>
</view>
limitCount 用于限制最多选择几张图片
- wxml部分
<view class="pic_content">
<view
class="image item"
wx:for="{{imageList}}"
wx:key="item"
>
<image class="pic" src="{{item}}" />
<image
class="icon_close"
src="https://file.40017.cn/groundtraffic/campus/campus-mina/mine/%E5%88%A0%E9%99%A4@2x.png"
data-item="{{item}}"
bind:tap="deleteImage"
/>
</view>
<view
class="chooseImage item"
bind:tap="chooseImage"
wx:if="{{imageList.length<limitCount}}"
>
<image src="https://file.40017.cn/groundtraffic/campus/campus-mina/mine/%E7%9B%B8%E6%9C%BA@2x.png"/>
<view class="count">{{imageList.length}}/{{limitCount}}</view>
</view>
</view>
js脚本
import {uploadFile} from '../../apis/upload'
import config from "../../utils/config";
Component({
properties: {
limitCount:{
type:Number,
value:4
}
},
data: {
imageList:[], //图片列表
},
methods: {
// 去选择照片
chooseImage(){
wx.chooseMedia({
count: this.properties.limitCount - this.data.imageList.length,
mediaType: ['image'],
sourceType: ['album', 'camera'],
maxDuration: 30,
camera: 'back',
success:(res)=> {
// 拿到资源本地临时路径list
let tempFilePaths = res.tempFiles.map(item=>item.tempFilePath)
// 循环上传至服务器
tempFilePaths.forEach(item=>{
wx.uploadFile({
//仅为示例,这里换上你们自己的接口地址,由服务端提供
url: `${config.schoolApi}/file/upload`,
filePath: item,
name: 'file',
formData: {},
success: (res)=>{
const imageUrl = JSON.parse(res.data).body
this.triggerEvent('change',[...this.data.imageList,imageUrl])
this.setData({
imageList:[...this.data.imageList,imageUrl]
})
},
fail(err){
console.log('上传上传失败',err);
}
})
})
}
})
},
// 删除图片
deleteImage(e){
let value = e.currentTarget.dataset.item
let imageList = this.data.imageList.filter(item=>item !== value)
this.setData({
imageList
})
this.triggerEvent('change',imageList)
}
}
})
css部分(less语法):
.pic_content{
display: grid;
grid-template-columns: repeat(auto-fill,148rpx);
grid-template-rows: repeat(auto-fill,148rpx);
gap:16rpx;
justify-content: space-around;
.image{
width: 148rpx;
height: 148rpx;
position: relative;
.pic{
width: 100%;
height: 100%;
border-radius: 20rpx;
background: rgb(59, 157, 199);
}
.icon_close{
position: absolute;
top: 0;
right: 0;
transform: translate(40%,-30%);
width: 32rpx;
height: 32rpx;
}
}
.chooseImage{
width: 148rpx;
height: 148rpx;
background: #efefef;
border-radius: 20rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
image{
width: 56rpx;
height: 56rpx;
margin-bottom: 16rpx;
}
.count{
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 28rpx;
color: #999999;
letter-spacing: 0;
line-height: 36rpx;
}
}
}