共计 6869 个字符,预计需要花费 18 分钟才能阅读完成。
上篇文章 uniapp 云函数教程①:登录篇, 咱们实现了简略的登录与注册逻辑。这篇文章咱们来实现一个商品列表的增删改查实战小我的项目。源码见文末。
扫码体验
或浏览器拜访
1. 数据库设计
咱们须要 2 张表:商品分类表 (mall_type
) 以及商品表 (mall_shop
), 商品表通过键key
来和商品分类表进行关联
1.1 商品分类表(mall_type
)
{
"bsonType": "object",
"required": [],
"permission": {
"read": false,
"create": false,
"update": false,
"delete": false
},
"properties": {
"_id": {"description": "ID,零碎主动生成"},
"name": {"description": "商品一级分类"}
}
}
1.2 商品表(mall_shop
)
{
"bsonType": "object",
"required": [],
"permission": {
"read": false,
"create": false,
"update": false,
"delete": false
},
"properties": {
"_id": {"description": "ID,零碎主动生成"},
"name": {"description": "商品名称"},
"key": {"description": "对应的一级分类 Id"},
"icon": {"description": "商品图片"},
"price": {"description": "价格"}
}
}
以下仅展现要害代码,具体代码可至源码查看
2. 商品列表界面开发
这里间接应用 uviewui 垂直分类的代码
3. 商品入库界面开发
3.1 商品分类性能开发
3.1.1 商品分类增加性能
新建云函数addType
,上传部署以及上传运行,增加 PATH/http/addtype
'use strict';
exports.main = async (event, context) => {const db = uniCloud.database(); // 代码块为 cdb
const dbCmd = db.command
const collection = db.collection('mall_type');
let queryStringParameters = event.queryStringParameters
let name = queryStringParameters['name']
let callback = {}
let isHasRes = await collection.where({name: dbCmd.eq(name)
})
.get()
// 简略做一下反复校验
if (isHasRes.data.length) {
callback = {
mesg: '商品分类反复',
code: 500
}
} else {
let res = await collection.add({name: queryStringParameters['name']
})
callback = {
mesg: '增加胜利',
code: 200,
id: res.id
}
}
return callback
};
增加表单以及接口
<u-form :model="form" ref="uForm">
<u-form-item label="商品分类" prop="name" label-width='150'>
<u-input v-model="form.name" placeholder="衣服、酒水等等" />
</u-form-item>
</u-form>
<u-button @click="submit" type="primary" > 提交 </u-button>
addType() {
uni.showLoading({title: '增加中'});
uni.request({
url: 'https://**.com/http/addtype',
data: {name: this.form.name},
success: (res) => {if (res.data.code == 200) {
uni.showToast({
icon: 'success',
title: '增加胜利'
});
this.$refs.uForm.resetFields()} else {
uni.showToast({
icon: 'error',
title: res.data.mesg || '增加失败'
});
}
},
complete: () => {uni.hideLoading();
this.getType()}
})
},
3.1.2 商品分类查问性能
新建云函数getType
,上传部署以及上传运行,增加 PATH/http/gettype
exports.main = async (event, context) => {const db = uniCloud.database(); // 代码块为 cdb
const res = await db.collection('mall_type').get()
return res
};
增加展现以后有多少分类界面,这里采纳 tag
的模式,也不便做删除
<u-tag :text="item.name" v-for="(item,index) in typeList" :key="index" />
getType() {
uni.showLoading({title: '获取分类中'});
uni.request({
url: 'https://**.com/http/gettype',
success: (res) => {this.typeList = res.data.data || []
uni.hideLoading()}
})
}
3.1.2 商品分类删除性能
新建云函数delType
,上传部署以及上传运行,增加 PATH/http/deltype
'use strict';
exports.main = async (event, context) => {const db = uniCloud.database();
const dbCmd = db.command
let id = event.queryStringParameters['id']
const collection = db.collection('mall_type');
let res = await collection.where({_id: dbCmd.eq(id)
}).remove()
return res
};
增加 tag
上的办法,以及删除二次弹窗
<u-tag :text="item.name" v-for="(item,index) in typeList" :key="index" closeable @close="tagClick(item,index)" />
<u-modal v-model="show" content="是否删除商品类型?" @confirm='confirm' show-cancel-button></u-modal>
tagClick(item, index) {
this.show = true;
this.selectItem = item
},
confirm() {
uni.request({
url: 'https://**.com/http/deltype',
data: {id: this.selectItem._id},
success: (res) => {
uni.showToast({
icon: 'success',
title: '删除胜利'
});
this.getType()}
})
}
3.2 商品性能开发
3.2.1 商品增加性能
新建云函数addShop
,上传部署以及上传运行,增加 PATH/http/addshop
'use strict';
exports.main = async (event, context) => {const db = uniCloud.database(); // 代码块为 cdb
const dbCmd = db.command
const collection = db.collection('mall_shop');
// 因为数据有 base64 图片,所以改为 body 获取
let body = JSON.parse(event.body)
let name = body['name']
let key = body['key']
let icon = body['icon']
let price = body['price']
let callback = {}
let isHasRes = await collection.where({name: dbCmd.eq(name)
})
.get()
if (isHasRes.data.length) {
callback = {
mesg: '商品反复',
code: 500
}
} else {
let res = await collection.add({
name: name,
key: key,
icon: icon,
price: price,
})
callback = {
mesg: '增加胜利',
code: 200,
id: res.id
}
}
// 返回数据给客户端
return callback
};
这里图片间接应用 base64
进行保留
增加表单以及接口
<u-form :model="form" ref="uForm" label-width='150'>
<u-form-item label="商品名称" prop="name">
<u-input v-model="form.name" placeholder="请输出商品名称" />
</u-form-item>
<u-form-item label="商品价格" prop="price">
<u-input v-model="form.price" placeholder="请输出商品价格" type='number' />
</u-form-item>
<u-form-item label="商品类型" label-width="150" prop="keyLabel">
<u-input type="select" :select-open="selectShow" v-model="form.keyLabel" placeholder="请抉择商品类型"
@click="selectShow = true"></u-input>
</u-form-item>
<u-form-item label="商品图片(<1MB)" prop="icon" label-width="150">
<u-upload :max-size="1 * 1024 * 1024" ref="uUpload" width="160" height="160" @on-choose-complete='changeImg' :auto-upload="false" max-count="1"></u-upload>
</u-form-item>
</u-form>
<u-button @click="submit" type="primary"> 提交 </u-button>
<u-select mode="single-column" :list="typeList" v-model="selectShow" @confirm="selectConfirm"></u-select>
图片上传改为自行上传,并取到图片的base64
changeImg(){let file = this.$refs.uUpload.lists[0]
var fr = new FileReader();
fr.onloadend = function(e) {this.form.icon = e.target.result;}.bind(this);
fr.readAsDataURL(file.file);
},
addShop() {
uni.showLoading({title: '增加中'});
uni.request({
url: 'https://f**.com/http/addshop',
method: 'POST',
data: {
key: this.form.key,
price: this.form.price,
name: this.form.name,
icon: this.form.icon,
},
success: (res) => {if (res.data.code == 200) {
uni.showToast({
icon: 'success',
title: '增加胜利'
});
// this.$refs.uForm.resetFields()} else {
uni.showToast({
icon: 'error',
title: res.data.mesg || '增加失败'
});
}
},
complete: () => {uni.hideLoading();
}
})
},
3.2.2 商品查问性能
新建云函数 getShop
,上传部署以及上传运行,增加 PATH/http/getshop
这里的数据格式依照 uview
商品模板的数据格式来组件即可
[
{
name: "xxx",
foods: [
{
name: "xx",
key: "xx",
icon: "xx",
price: "xx"
}
]
}
];
'use strict';
exports.main = async (event, context) => {const db = uniCloud.database(); // 代码块为 cdb
const dbCmd = db.command
// 查问商品分类
const typeRes = await db.collection('mall_type').get()
const collection = db.collection('mall_shop');
let shopList = []
let typeList = typeRes.data || []
for (var i = 0; i < typeList.length; i++) {
// 查问商品分类下的所属商品
let list = await collection.where({key: dbCmd.eq(typeList[i]._id)
})
.get()
let obj = {name: typeList[i].name,
foods: list.data || []}
shopList.push(obj)
}
return {data: shopList}
};
回到方才的商城模板页面,增加获取商品的代码, 并将 tabbar
的模仿数据替换为实在数据
getShop(){
uni.showLoading({title: '获取商品中'});
uni.request({
url: 'https://f**.com/http/getShop',
success: (res) => {this.tabbar = res.data.data || []
uni.hideLoading()}
})
},
3.2.3 商品删除性能
新建云函数delShop
,上传部署以及上传运行,增加 PATH/http/delshop
'use strict';
exports.main = async (event, context) => {const db = uniCloud.database(); // 代码块为 cdb
const dbCmd = db.command
let id = event.queryStringParameters['id']
const collection = db.collection('mall_shop');
let res = await collection.where({_id: dbCmd.eq(id)
}).remove()
// 返回数据给客户端
return res
};
在商城列表,咱们为商品增加一个长按 (longpress
) 删除的性能, 大概在mallMenu.vue
24 行。并增加二次确认弹窗
<view class="thumb-box" v-for="(item1, index1) in item.foods" :key="index1" @longpress='del(item1)'>
<image class="item-menu-image" :src="item1.icon" mode=""></image>
<view class="item-menu-name">{{item1.name}}</view>
</view>、、、、、、<u-modal v-model="show" content="是否删除商品?" @confirm='confirm' show-cancel-button></u-modal>
del(item){
this.delItem = item
this.show = true
},
confirm(){
uni.request({
url: 'https://**.com/http/delshop',
data: {id: this.delItem._id},
success: (res) => {
uni.showToast({
icon: 'success',
title: '删除胜利'
});
this.getShop()}
})
}
至此,商品的入库、查看、删除性能便开发实现了
结尾
商品图片素材包下载
源码下载
源码下载 gitee