效果图:
1.uni-app 实现微信小程序云开发的详细配置
请查看这篇文章:
2.上传图片的云函数
先在云开发控制台建立集合名称,用于保存图片上传成功后返回的fileID
云函数在微信开发者工具编写,方便上传函数。
3.多图上传页面
在Hbilder X 编写前端页面代码
<template>
<view class="content">
<!-- 选择图片区域 -->
<view class="images_box">
<block v-for="(item, index) in imgTempUrl" :key="index">
<view class='img-box'>
<image class='img' :src='item' mode='aspectFill'></image>
<view class='img-delete' @click='imgDelete' :data-delindex="index">
<image class='img' src='../../static/delete.png' ></image>
</view>
</view>
</block>
<view class='img-box' @click='imgAdd' v-if="imgTempUrl.length<9" >
<image class='img' src='../../static/add.png'></image>
</view>
</view>
<button class="btn" type="primary" @click="upImg">上传图片到云存储</button>
<button class="btn" type="primary" @click="seeImg">浏览云图片</button>
</view>
</template>
<script>
export default {
data() {
return {
num:0, //用于上传计数
listLength:0,
imgTempUrl:[]
}
},
methods: {
//选择添加图片
imgAdd() {
wx.chooseImage({
count: 9,
sizeType: ['original', 'compressed'],
sourceType: ['album','camera'],
success: (res) => {
if (this.imgTempUrl.length === 0) {
this.imgTempUrl = res.tempFilePaths
} else if (this.imgTempUrl.length < 9) {
this.imgTempUrl = this.imgTempUrl.concat(res.tempFilePaths); //concat追加到数组
}
}
})
},
//上传按钮
upImg() {
var listLength = this.imgTempUrl.length
this.listLength = listLength
if (listLength > 0) {
uni.showLoading({
title: '上传中...'
})
for(var n=0; n < listLength; n++) { //循环调用上传函数
this.upload(this.imgTempUrl[n])
}
}
},
//上传函数
upload(filePath) {
wx.cloud.uploadFile({
filePath: filePath, //要上传的文件对象
cloudPath: 'images/' + Date.now() + '.jpg', //保存在云端的路径及文件名(这里以时间戳命名)
success: (res) => {
console.log(res.fileID)
let fileID = res.fileID //云端返回的图片地址
wx.cloud.callFunction({ //调用云端函数,把图片地址写入表
name: 'addImage', //云函数名称
data: { //提交给云端的数据
fileID: fileID
},
success: (res) => {
console.log('fileID 插入成功')
//console.log(res)
},
fail: (err) => {
console.log(err)
},
complete: () => { //箭头函数能直接使用 this
this.num = this.num + 1
if(this.num == this.listLength) { //上传完成后清空图片,关闭提示框
this.imgTempUrl = ''
this.num = 0
uni.hideLoading()
}
}
})
}
})
},
// 删除已经选择的图片
imgDelete: function (e) {
//获取要删除的图片的下标,否则删除的永远是第一张 ,对应 <view class='img-delect' @click='imgDelete' :data-delindex="index">
let index = e.currentTarget.dataset.delindex;
this.imgTempUrl.splice(index, 1);
},
seeImg() {
uni.navigateTo({ //跳转到指定页面
url: "../browseImage/browseImage",
});
}
}
}
</script>
<style>
.content{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.btn{
margin: 10px;
width: 200px;
}
/* 图片 */
.images_box{
width: 98%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
background-color: white;
margin: 10rpx;
}
.img-box{
border: 1rpx;
border-style: solid;
border-color: rgba(0, 0, 0, 0.452);
width: 200rpx;
height: 200rpx;
margin-left: 25rpx;
margin-top: 20rpx;
margin-bottom: 20rpx;
position: relative;
}
.img{
width: 100%;
height:100%;
}
/* 删除图片 */
.img-delete{
width:50rpx;
height:50rpx;
border-radius:50%;
position:absolute;
right:-20rpx;
top:-20rpx;
}
</style>
4.分页加载图片的云函数 selectImages
// 云函数入口文件
const cloud = require('./node_modules/wx-server-sdk')
cloud.init()
const db = cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
var filter = event.filter ? event.filter : {} ; //筛选条件,默认为空,格式 {key:'values'}
var pageIndex = event.pageIndex ? event.pageIndex : 1 ; //当前第几页,默认为第一页
var pageSize = event.pageSize ? event.pageSize : 10 ; //每页取多少条记录,默认为10条
const countResult = await db.collection('Images_base').where(filter).count() //获取集合中的总记录数
const total = countResult.total //得到总记录数
const totalPage = Math.ceil(total / pageSize) //计算页数
var hasMore ; //提示前端是否还有数据
if (pageIndex > totalPage || pageIndex == totalPage) { //如果没有数据了,就返回false
hasMore = false
} else {
hasMore = true
}
//查询数据并返回给前端
return await db.collection('Images_base').where(filter).skip((pageIndex - 1) * pageSize).limit(pageSize).orderBy('createTime','desc').get().then( res => {
res.hasMore = hasMore ;
return res ; // 返回json给客户端
})
}
5.浏览图片页面 vue
<template>
<view class="free-panel-title">
<view class="free-WaterfallFlow">
<block>
<view class="flex-wrap" v-for="(item,index) in imgList" :key="index" v-if="index % 2 != 0">
<image mode="widthFix" :src="item.fileID" :data-src="item.fileID" @click="clickimg" ></image>
<view>评论</view>
<view> {{item.createTime}} </view>
</view>
</block>
<block>
<view class="flex-wrap" v-for="(item,index) in imgList" :key="'2-'+ index" v-if="index % 2 == 0">
<image mode="widthFix" :src="item.fileID" :data-src="item.fileID" @click="clickimg" ></image>
<view>评论</view>
<view> {{item.createTime}} </view>
</view>
</block>
</view>
<!--返回顶部-->
<view class="top" :style="{'display':(flag===true? 'block':'none')}">
<image class="topc" @click="top" src="../../static/top.png" ></image>
</view>
</view>
</template>
<script>
export default {
data() {
return {
hasMore:false ,
pageIndex: 1 ,
imgList: [],
flag: false
}
},
onLoad() {
this.imgLoad()
},
// 上拉触底事件
onReachBottom:function( ) {
if (this.hasMore) {
this.imgLoad() //调用函数
setTimeout(() => {
uni.stopPullDownRefresh();
}, 1000);
} else {
uni.showToast({
title: '没有更多数据了!',
icon:'none'
})
}
},
methods: {
imgLoad() {
wx.showLoading({
title: '加载中...'
})
wx.cloud.callFunction({ //调用云函数
name:'selectImages', //云函数名称
data:{ //以下是云函数需要传入的参数
filter:{}, //筛选条件
pageIndex: this.pageIndex , //第几页
pageSize: 20 //每页的记录条数
},
success: (res) => {
//console.log(res)
this.imgList = this.imgList.concat(res.result.data) //云端返回的查询数据,追加到数组imgList
this.imgList.forEach( item => { //循环调用函数happenTimeFun,将时间戳转为年月日
item.createTime = this.happenTimeFun(item.createTime)
})
this.hasMore = res.result.hasMore //云端返回的是否有更多数据
if (this.hasMore) {
this.pageIndex = this.pageIndex + 1
}
},
fail(e) {
console.log(e)
},
complete: () => {
uni.hideLoading()
}
})
},
happenTimeFun(num){ //时间戳数据处理
let date = new Date(num); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
let y = date.getFullYear();
let MM = date.getMonth() + 1;
MM = MM < 10 ? ('0' + MM) : MM;//月补0
let d = date.getDate();
d = d < 10 ? ('0' + d) : d;//天补0
let h = date.getHours();
h = h < 10 ? ('0' + h) : h;//小时补0
let m = date.getMinutes();
m = m < 10 ? ('0' + m) : m;//分钟补0
let s = date.getSeconds();
s = s < 10 ? ('0' + s) : s;//秒补0
return y + '-' + MM + '-' + d; //年月日
//return y + '-' + MM + '-' + d + ' ' + h + ':' + m+ ':' + s; //年月日时分秒
},
// 图片预览
clickimg(event) {
var imgurl = event.currentTarget.dataset.src
var currentUrl = event.currentTarget.dataset.src //获取点击图片的地址, **对应<template>里面的 :src="item.src"
uni.previewImage({
urls: [imgurl], //这里是单图 . 需要预览的全部图片地址,这个数组是必须的,要用[]
current: currentUrl, //当前显示图片的地址
})
},
//回到顶部
top() {
uni.pageScrollTo({
scrollTop: 0,
duration: 300
});
},
onPageScroll(e) { //根据距离顶部距离是否显示回到顶部按钮
if(e.scrollTop>600){ //当距离大于600时显示回到顶部按钮
this.flag=true
}else{ //当距离小于600时隐藏回到顶部按钮
this.flag=false
}
}
}
}
</script>
<style>
.free-WaterfallFlow{
width:96%;
column-count:2; /* 分隔的列数 */
}
.free-WaterfallFlow .flex-wrap{
display: inline-block;
width:98%;
margin-left:3%;
margin-bottom:3%;
padding:2%;
padding-top:5%;
border:0px solid #cc22b0; /* 边框 */
box-shadow: 0 2px 2px rgba(34, 25, 25, 0.4); /* 框阴影 */
text-align: center; /* 框内元素居中对齐 */
}
.flex-wrap image{
width:95%;
margin:0 auto;
}
.flex-wrap view:nth-child(2){
font-size:15px;
padding:2% 0;
color:#717171;
}
.flex-wrap view:nth-child(3){
font-size:13px;
padding:2% 0;
color:#aaa;
text-align: right;
}
/* 回到顶部 */
.top {
position: relative;
display: none; /* 先将元素隐藏 */
}
.topc {
height: 30px;
width: 30px;
position: fixed;
right: 5px;
top: 80%;
}
</style>