图片画廊示例
图片画廊是一个简单的小程序示例,结合小程序客户端和 Basement 后端,完成一个具备前后端功能的完整小程序。
前提条件
创建小程序
- 登录 蚂蚁金服开放平台,选择 开发者中心 > 小程序 > 创建 。
- 填写 基本信息,点击 创建 按钮,创建应用名为 示例应用 小程序。
说明:一个账号最多可以创建 10 个小程序;未提交过审核的小程序可以删除,删除的小程序不在计数范围。
创建 Basement
- 在 我的小程序 页面,选择已经创建的小程序,点击 查看,进入 开发管理 页面。
- 点击左侧导航栏的 云服务(公测),在 云服务列表 页面点击 创建云服务 > 创建 Basement 。
- 在 创建 Basement 页面,填入 应用名称 和 描述 (选填),点击 创建。
说明:每个账号可免费创建一个 Basement 服务;当前测试环境该方案免费提供,但若 连续 7 日小程序没有访问量,并且未部署过代码 ,环境资源会被自动回收。
准备开发环境
打开小程序开发者工具,点击 新建项目。
在新建项目向导中,选择 小程序,选择 图片画廊示例,点击 下一步。
输入 项目名称,项目路径会自动填充,选择 Basement 为后端服务,点击 完成。
在 IDE 的客户端依赖页面,安装 @ant-basement/miniprogram-sdk。
说明:如果列表中找不到,可以在依赖框中输入 @ant-basement/miniprogram-sdk 完成添加。
- 点击 云服务:请选择 > 选择此前已经创建好的 Basement 服务作为关联的云服务。
部署云函数
点击 云服务 唤起菜单,点击 上传部署服务端代码 提交云函数部署。
说明:将 server 目录的代码作为云函数进行上传和部署。部署成功相当于完成云函数的代码发布,部署前请注意区分测试环境和生产环境的区别。
预览和上传
点击 刷新图标 可以在 IDE 模拟器 中查看预览效果;还可以点击 预览 ,使用 支付宝扫描二维码 在手机上实现真机预览。
点击 上传 将小程序上传到开放平台,具体操作请参考 小程序提审、发布流程。
后端代码介绍
获取用户信息
小程序是运行在支付宝上的,首先需要获取支付宝用户的基础信息,用于完善用户头像、昵称等信息。我们需要创建一个云应用,通过支付宝 OpenAPI,当用户访问小程序的时候将对应信息获取到并显示在页面上。
- 在 server 目录增加 getUserInfo/index.js 文件,用于编写和存放云函数的代码。
'use strict';
module.exports = async (ctx) => {
// 从支付宝 OpenAPI 获取用户信息
const user = await ctx.basement.openapi.alipay.exec('alipay.user.info.share');
// 返回用户信息
return user;
};
- 在 server 目录修改 serverless.yml 文件,将 getUserInfo/index 作为一个 function 服务。在这里相当于定义云函数的访问别名和云函数路径的关系。
functions:
getUserInfo:
handler: getUserInfo/index
- 重新点击 上传部署服务端代码 提交云函数部署。
- 在首页,有当前 用户的头像 。通过调用云函数在支付宝获取用户信息,并显示到页面上。
client/pages/index/index.js 文件中,修改 onShow 方法 ,在页面初始化时获取用户信息并更新页面。
javascript // 显示指定当前用户的图片列表 onShow() { basement.function.invoke('getUserInfo').then((res) => { if (res.success) { const user = res.result; this.setData({ user }); this._getImages(user); my.hideLoading(); } }).catch(console.error); }
读取图片列表
在首页,需要从数据库将 图片列表 读取出来。
client/pages/index/index.js 文件中,在 onShow 方法 获取图片列表并更新页面。(本示例中获取图片列表的处理封装在 _getImage 方法中)
// 获取特定用户的图片列表
_getImages(user) {
basement.db.collection('images')
.find({ userId: user.userId }, { sort: { uploadTime: -1 } })
.then(({ result: images }) => {
images.map((item) => {
item.uploadTime = new Date(item.uploadTime).toDateString();
return item;
})
const noImages = images && images.length === 0 ? true : false;
this.setData({ images, noImages });
})
.catch(console.error);
}
更新图片信息
用户可以在图片列表上点击 重命名 ,在对话框输入新的名称,对图片名称进行更新。
client/pages/index/index.js 文件中,在 rename 方法 中显示对话框采集新的图片名称,最后刷新列表。
// 变更图片名称的事件处理
rename(e) {
const dataset = e.target.dataset;
my.prompt({
title: '修改名称',
message: '请输入新的图片名称:',
placeholder: '',
okButtonText: '确定',
cancelButtonText: '取消',
success: (result) => {
if (result.ok) {
basement.db.collection('images').updateOne(
{ _id: dataset.itemId },
{
$set: {
text: result.inputValue,
}
}
).then(() => {
this._getImages(this.data.user);
}).catch(console.error);
}
},
});
}
删除图片
用户可以在图片列表上点击 删除 ,销毁一张图片。
client/pages/index/index.js 文件中,在 delete 方法 中显示确认对话框,确认后删除图片并刷新列表。
// 删除图片的事件处理
delete(e) {
const dataset = e.target.dataset;
// 确认和删除图片
my.confirm({
title: '删除图片',
content: '是否确认删除该图片?',
confirmButtonText: '删除',
cancelButtonText: '取消',
success: (result) => {
if (result.confirm) {
basement.db.collection('images').deleteOne({
'_id': dataset.itemId,
'userId': this.data.user.userId,
}).then(() => {
// 刷新任务列表
this._getImages(this.data.user);
}).catch(console.error);
}
},
});
}
添加图片
当用户点击 添加图片 新增页面,在这里填写 图片名称 和上传 图片 后,可以增加一个新的图片记录。
- 上传图标:client/pages/add-image/add-image.js 文件中,在 uploadImg 方法 完成图片上传和存储。
// 选择并上传图片,获得图片 URL
attach() {
my.chooseImage({
chooseImage: 1,
success: res => {
const path = res.apFilePaths[0];
const options = {
filePath: path,
headers: {
contentDisposition: 'attachment',
},
};
basement.file.uploadFile(options).then((image) => {
this.setData({
imageUrl: image.fileUrl,
});
}).catch(console.error);
},
});
}
- 新增图片:client/pages/add-image/add-image.js 文件中,在 add 方法 完成新的图片内容新增。
// 将新的图片内容添加到当前用户的图片列表中
add() {
// 如果图片名称没有填,或者没有上传图片,则进行提示
if (this.data.inputValue == '' || !this.data.imageUrl) {
my.alert({
title: '添加失败',
content: '请填写图片名称和上传图片。',
buttonText: '我知道了',
});
// 正常情况,写入数据存储
} else {
basement.function.invoke('getUserInfo').then((res) => {
if (res.success) {
const user = res.result;
basement.db.collection('images').insertOne({
text: this.data.inputValue,
url: this.data.imageUrl ? this.data.imageUrl : false,
userId: user.userId,
uploadTime: new Date(),
}).then(() => {
my.navigateBack();
}).catch(console.error);
}
}).catch(console.error);
}
}
查看图片数量
为了让开发者了解在云函数中如何调用数据存储服务,本示例中我们在云函数对图片数量进行了统计。
- 在 server 目录增加 imageAnalytics/index.js 文件,用于编写和存放云函数的代码。
'use strict';
module.exports = async (ctx) => {
const user = await ctx.basement.openapi.alipay.exec('alipay.user.info.share');
const images = await ctx.basement.db.collection('images').find({ userId: user.userId });
// 如果没有任务,返回 null
if (!images.affectedDocs) {
return null;
}
// 获取结果值
const total = images.result.length || 0;
return {
total: total,
};
};
- 在 server 目录修改 serverless.yml 文件,将 imageAnalytics/index 作为一个 function 服务。
functions:
imageAnalytics:
handler: imageAnalytics/index
getUserInfo:
handler: getUserInfo/index
重新点击 上传部署服务端代码 提交云函数部署。
在首页点击 用户头像 ,前往 我的统计页面 ,在页面上显示统计信息。
client/pages/me/me.js 文件中,修改 onShow 方法 ,在页面初始化时获取图片统计数量并显示出来。
javascript // 请求云函数获取图片总数 onShow() { basement.function.invoke('getUserInfo').then((res) => { if (res.success) { this.setData({ user: res.result }); basement.function.invoke('imageAnalytics').then((imageRes) => { my.hideLoading(); if (imageRes.success) { this.setData({ analytics: imageRes.result || { total: 0 } }); } }).catch(console.log); } }).catch(console.log); }