注册
web

手把手教你做个煎饼小程序,摊子开起来

前言


周饼伦在街头摊煎饼,摊后人群熙熙攘攘。他忙得不可开交,既要记住面前小哥要加的培根,又要记住身后奶奶要加的生菜,这时又来了个小妹妹,点的煎饼既要培根又要腊肠。他把鸡蛋打进煎饼后,竟突然忘了前面光头大叔要加的料,是火腿还是鸡柳?一时记不清,好像是火腿,对。然而当把煎饼交给大叔,大叔却怒了,说要的是鸡柳。😡


这可咋办?周饼伦赶忙道歉,大叔却语重心长地说:“试试用小程序云开发吧!最近的数据模型新功能好用得很!” 周饼伦亮出祖传手艺,边摊煎饼边开发小程序,把新开发的小程序点餐页面二维码贴在摊前。从此再没出过错,终于能安心摊煎饼啦!


设计思路


图片


客户扫摊子上面贴的二维码后,会进入点餐页面,在选好要加的配料之后,点击确定就可以点餐,随后,即可在云后台上看到食客提交的数据


图片


实现过程


周饼伦就把当前摊位的主食、配菜,以及各自相应的价格贴在了摊位上,也要把食客的点餐内容记在脑里或者用笔写在纸上。


点餐页要实现两个功能:1.展示当前摊位有的主食、配菜、口味 2.提交订单到周饼伦的订单页面。


煎饼摊子主食(staple food)目前只有摊饼、青菜饼,主食下面有的配菜(side dish),有鸡柳、生菜、鸡蛋、火腿、腊肠。


同理,数据库里面也需要呈现相应的结构。


数据表的实现


数据模型现在提供了一种便捷的能力来,可以快速创建一套可用的数据表来记录摊煎饼的相关数据。


图片


在云后台中新增了一个基于 MySQL 的数据模型,数据模型相当于一张纸,可以在上面记录任何想要记录的数据,比如周饼伦摊位的提供的菜品


图片


创建了基于云开发MySQL数据库的主食表,主食表中包含主食名称,主食价格


图片


图片


字段的详细设置如下


图片


图片


加了主食、配菜两个表之后,将当前的主食和配菜一起加进数据表中

图片


图片


现在就实现了记录当前摊子的主食和配菜。还需要一个订单表,来记录用户的点餐数据


图片


配菜的类型是一个数组文本,用来记录配菜的类型,结构如下


图片


接着需要分别设置每个数据模型的权限。在使用小程序查看订单时,也是以用户的身份来读取的,所以,需要配置用户权限,通过页面访问来控制用户能够访问到哪些页面


图片


图片


图片


至此,数据表就已经大功告成!现在完全可以使用三个表来记录当前摊子的菜品、营业情况。


但是,别忘了周饼伦的目的不止于此,为了周饼伦实现早日暴富,当上CEO,所以,还要利用小程序实现一个界面,来给”上帝“们点餐,并且提供各位CEO查看订单


小程序实现过程


一. 初始化 SDK


在云后台的数据管理中的右侧中,可以方便的查询到使用的文档


图片


新建一个基于云开发的小程序,删除不必要的页面,并且按照文档的步骤进行初始化👇


1.按照指引在 miniprogram 目录下初始化 npm 环境并安装 npm 包


请注意,这里需要在 miniprogram 目录下初始化 npm ,不然需要编辑 project.config.json 手动指定 npm 包的位置


在 miniprogram 目录下打开终端


图片


2.初始化当前 npm 并且安装 @cloudbase/wx-cloud-client-sdk npm 包


npm init -y & npm install @cloudbase/wx-cloud-client-sdk --save

图片


3.在小程序中构建 npm


图片


4.在小程序 app.js 中初始化环境


// app.js
App({
globalData: {
// 在这里提供全局变量 models 数据模型方法,方便给页面使用
models: null
},
onLaunch: async function () {
const {
init
} = require('@cloudbase/wx-cloud-client-sdk')
// 指定云开发环境 ID
wx.cloud.init({
env: "ju-9g1guvph88886b02",
});
const client = init(wx.cloud);
const models = client.models;
// 可以取消注释查看效果
// const { data } = await models.stapleFood.list({
// filter: {
// where: {}
// },
// pageSize: 10,
// pageNumber: 1,
// getCount: true,
// });
// console.log('当前的主食数据:');
// console.log(data.records);
}
});

二. 下单页面的实现


首先创建一个页面 goods-list 页面作为首页


顾客如果浏览下单页面,那么就需要看到当前可以选择的主食、配菜,还有他们分别的价格。所以首先我们需要把主食、配菜加载进来


// 加载主食
const stapleFood = (await models.stapleFood.list({
filter: {
where: {}
},
pageSize: 100, // 一次性加载完,
pageNumber: 1,
getCount: true,
})).data.records;

// 加载配菜
const sideDish = (await models.sideDish.list({
filter: {
where: {}
},
pageSize: 100, // 一次性加载完,
pageNumber: 1,
getCount: true,
})).data.records;

// pages/goods-list/index.js
Page({
data: {
// 总价格
totalPrize: 0,
// 选中的主食
selectedStapleFoodName: '',
// 选中的配菜
selectedSideDishName: [],
// 所有的主食
stapleFood: [],
// 所有的配菜
sideDish: [],

以下是全部的js代码


// pages/goods-list/index.js
Page({
data: {
// 总价格
totalPrize: 0,
// 选中的主食
selectedStapleFoodName: '',
// 选中的配菜
selectedSideDishName: [],
// 所有的主食
stapleFood: [],
// 所有的配菜
sideDish: [],
},

async onLoad(options) {
const models = getApp().globalData.models;
console.log('models', models)

// 加载主食
const stapleFood = (await models.stapleFood.list({
filter: {
where: {}
},
pageSize: 100, // 一次性加载完,
pageNumber: 1,
getCount: true,
})).data.records;

// 加载配菜
const sideDish = (await models.sideDish.list({
filter: {
where: {}
},
pageSize: 100, // 一次性加载完,
pageNumber: 1,
getCount: true,
})).data.records;

console.log({
stapleFood,
sideDish
});

this.setData({
stapleFood: stapleFood,
sideDish: sideDish
})
},

// 选中主食
onSelectStapleFood(event) {
this.setData({
selectedStapleFoodName: event.currentTarget.dataset.data.name
});

this.computeTotalPrize();
},

// 选中配菜
onSelectedSideDish(event) {
console.log(event);
// 选中配菜名字
const sideDishName = event.currentTarget.dataset.data.name;

// 如果已经选中,则取消选中
if (this.data.selectedSideDishName.includes(sideDishName)) {
this.setData({
selectedSideDishName: this.data.selectedSideDishName.filter((name) => (name !== sideDishName))
});
} else {
// 未选中,则选中
this.setData({
selectedSideDishName: this.data.selectedSideDishName.concat(sideDishName)
});
}

this.computeTotalPrize();
},

// 重新计算价格
computeTotalPrize() {
// 主食价格
let staplePrize = 0;
if (this.data.selectedStapleFoodName) {
staplePrize = this.data.stapleFood.find((staple) => staple.name === this.data.selectedStapleFoodName).prize;
}

// 配菜价格
let sideDish = 0;
this.data.selectedSideDishName.forEach((sideDishName) => {
sideDish += this.data.sideDish.find((sideDishItem) => (
sideDishItem.name === sideDishName
)).prize;
});

// 总价格
this.setData({
totalPrize: staplePrize + sideDish
})
},

// 提交
async onSubmit() {
// 提示正在加载中
wx.showLoading({
title: '正在提交订单',
});

const models = getApp().globalData.models;
const { data } = await models.order.create({
data: {
served: false, // 是否已出餐
sideDish: this.data.selectedSideDishName, // 配菜
stapleFoodName: this.data.selectedStapleFoodName, // 主食名称
prize: this.data.totalPrize, // 订单总价格
}
});

console.log(data);
wx.hideLoading();
}
});

接着来实现页面


<!--pages/goods-list/index.wxml-->
<view>
<view class="title">
<image src='/asset/pancake.png'></image>
<text class="title">请选择主食</text>
</view>

<!-- 主食展示 -->
<view class="staple-food">
<view wx:for="{{stapleFood}}" wx:key="_id">
<view bindtap="onSelectStapleFood" data-data="{{item}}" class="staple-food-item {{selectedStapleFoodName === item.name ? 'selected' : ''}}">
<image src="{{item.imageUrl}}"></image>
<view class="prize">{{item.prize}}¥</view>
</view>
</view>
</view>

<!-- 选择配菜 -->
<view class="title">
<image src='/asset/sideDish.png'></image>
请选择配菜
</view>

<!-- 配菜展示 -->
<view class="side-dish">
<view wx:for="{{sideDish}}" wx:key="_id">
<!-- 使得class动态绑定支持 includes 语法 -->
<wxs module="tool">
var includes = function (array, text) {
return array.indexOf(text) !== -1
}
module.exports.includes = includes;
</wxs>
<view class="side-dish-item {{tool.includes(selectedSideDishName, item.name) ? 'selected' : ''}}" bindtap="onSelectedSideDish" data-data="{{item}}">
<image src="{{item.imageUrl}}"></image>
<view class="prize">{{item.prize}}¥</view>
</view>
</view>
</view>

<!-- 底部菜单 -->
<view class="bottom-content">
<view class='bottom-info'>
<view wx:if="{{!!selectedStapleFoodName}}">主食:{{selectedStapleFoodName}}</view>
<view wx:if="{{selectedSideDishName.length !== 0}}">配菜:{{selectedSideDishName}}</view>
</view>

<view class="bottom-operate">
<view class="total-prize">当前价格<text class="prize">{{totalPrize}}¥</text></view>
<view class="submit-button {{!selectedStapleFoodName ? 'disabled' : ''}}" bind:tap="onSubmit">下单</view>
</view>
</view>
</view>

再添加一点点的样式


/* pages/goods-list/index.wxss */
.title {
display: flex;
align-items: center;
gap: 16rpx;
padding: 0 20rpx;
}

.title image {
height: 46rpx;
width: 46rpx;
}

.staple-food {
display: flex;
margin-bottom: 60rpx;
overflow: auto;
}

.staple-food-item {
margin: 20rpx 10rpx;
display: flex;
flex-direction: column;
border: 1px solid #f3f0ee;
box-shadow: 6rpx 6rpx 6rpx #dfdfdf, -6rpx -6rpx 6rpx #dfdfdf;
border-radius: 6rpx;
padding: 8rpx;
}

.staple-food-item.selected, .side-dish-item.selected {
box-shadow: 6rpx 6rpx 6rpx #58b566, -6rpx -6rpx 6rpx #58b566, 6rpx -6rpx 6rpx #58b566, -6rpx 6rpx 6rpx #58b566;
}

.staple-food-item image {
border-radius: 6rpx;
width: 300rpx;
height: 300rpx;
}

.prize {
padding: 6rpx 6rpx 0;
text-align: right;
color: orangered
}

.side-dish {
padding: 20rpx 12rpx;
display: flex;
gap: 12rpx;
overflow: auto;
}

.side-dish image {
height: 200rpx;
width: 200rpx;
}

.side-dish-item {
border-radius: 8px;
padding: 16rpx;
box-shadow: 6rpx 6rpx 6rpx #dfdfdf, -6rpx -6rpx 6rpx #dfdfdf;
}

.bottom-content {
position: absolute;
bottom: 0;
left: 0;
right: 0;
}

.bottom-info {
padding: 30rpx;
display: flex;
flex-direction: column;
color: grey;
font-size: 0.5em;
}

.bottom-content .total-prize {
padding: 0 30rpx;
}

.bottom-operate {
border-top: 1px solid #dfdfdf;
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
height: 100rpx;
}

.submit-button {
width: 350rpx;
color: white;
background: #22b85c;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}

.submit-button.disabled {
background: grey;
/* 注意,这里设置了当按钮置灰的时候,不可点击 */
pointer-events: none;
}

于是,煎饼摊的小程序就大功告成了!


接着就可以在云后台管理订单了,在将订单完成之后,即可在云后台将订单的状态修改成已完成。


图片


我们还可以做的更多…


是否可以在订单中新增一个点餐号,这样就知道是哪个顾客点的餐?是否可以使用数据模型的关联关系将配菜、主食和订单关联起来?


是否可以在小程序中创建一个管理订单的页面?是否可以添加优惠券数据表,来给客户一些限时优惠?


期待大家的体验反馈!


代码地址:github.com/vancece/qiL…


点击体验:tcb.cloud.tencent.com/cloud-admin…


作者:腾讯云云开发
来源:juejin.cn/post/7413376270518042651

0 个评论

要回复文章请先登录注册