original intention
From the explosion of wechat Xiaocheng in 2018 to the current applet and cross platform applet framework. It has appeared in everyone's life for three years, and has been used more and more deeply. After several years of development, wechat has officially provided a cloud development model. I was thinking that as a developer, I could achieve the original goal of full stack engineers. So this article is the first step for me to become a full stack engineer, and I hope it is also your first step.
Project introduction
My friend opened an optical shop and told me if he could get user information on his mobile phone and maintain the customer information of his eye shop. I think it's not just a small program. So I looked for the design draft of this kind of glasses store on the Internet. After finding it, according to his needs, I had a small program to make an appointment to the store for business, order maintenance and user information maintenance. With the demand and design, I can do a project by myself when I happen to use the cloud development of small programs.
In the process of this project, the problems encountered are worth recording. Therefore, I share all my achievements in the process, hoping to help some children's shoes.
Project Preview
Call interface
User registration
Order submission
Order maintenance
Project information
Github source address: road passenger glasses Welcome Fork if necessary. If you like, please give a Star~
Project content
Project directory
├── README.md ├── cloudfunctions // Here is the code of the cloud function │ ├── allOrderInfo │ │ ├── config.json │ │ ├── index.js │ │ └── package.json │ ├── orderInfo │ │ ├── config.json │ │ ├── index.js │ │ └── package.json │ ├── productInfo │ │ ├── config.json │ │ ├── index.js │ │ └── package.json │ ├── roleInfo │ │ ├── config.json │ │ ├── index.js │ │ └── package.json │ └── userInfo │ ├── config.json │ ├── index.js │ ├── package-lock.json │ └── package.json ├── img // Here are some local pictures, because cloud storage has been used in my project to display pictures, which is convenient to display pictures after pulling the code │ ├── T1.png │ ├── T2.png │ ├── T3.png │ ├── T3_more.png │ ├── banner1.jpeg │ ├── banner2.jpeg │ └── qrcode.jpg ├── miniprogram // Applet code directory │ ├── app.js │ ├── app.json │ ├── app.wxss │ ├── components │ │ └── cloudTipModal │ ├── envList.js │ ├── images │ │ ├── BLUE_2.jpeg │ │ ├── GLASSES.jpeg │ │ ├── USER.png │ │ ├── arrow.png │ │ ├── black.jpeg │ │ ├── blue.jpeg │ │ ├── call.png │ │ ├── class.jpeg │ │ ├── detail.jpeg │ │ ├── glass │ │ ├── jinhangzhong.png │ │ ├── pink.jpeg │ │ ├── quchu.png │ │ ├── submit.png │ │ ├── tab │ │ ├── tea.jpeg │ │ ├── weifukuan.png │ │ ├── white.jpeg │ │ └── yiwancheng.png │ ├── miniprogram_npm │ │ └── @miniprogram-component-plus │ ├── package-lock.json │ ├── package.json │ ├── pages │ │ ├── allOrderInfo │ │ ├── appointment //make an appointment │ │ ├── confirmOrder │ │ ├── glasses //optician │ │ ├── goodsDetail │ │ ├── index //home page │ │ ├── map │ │ ├── orderInfo │ │ ├── orderResult │ │ ├── updateOrder │ │ ├── user //Personal Center │ │ └── userInfo │ └── sitemap.json ├── project.config.json ├── project.private.config.json └── uploadCloudFunction.sh
Project configuration during cloud development
Cloud development initialization and other configurations are clearly written in the official documents. You can go to any problem Official documents Query.
Let's start by introducing the configuration of the project at run time:
Create four new collections in the cloud development database directory: order_info,product_info,role_info,user_info.
order_info stores user order information and product info_ Info stores product information and roles_ Info stores role information and user info_ Info stores user information
Upload and deploy the cloud functions in the cloudfunctions directory
User registration
Wechat applet user information authorization has really been changed many times. Now it is necessary to obtain user avatar and nickname information getUserProfile API Originally, the Button component can be used to obtain information with open type, but the user information cannot be displayed on the real machine.
pages/user/index wxml code: <view class="header-icon-box color-fff text-center"> <block wx:if="{{islogin}}"> <image class="header-icon block" src="/images/USER.png"></image> <!-- <button class="header-icon-btn bg-blue color-fff" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">Get phone number</button> --> <button wx:if="{{userParam.errMsg}}" class="header-icon-btn bg-blue color-fff" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">Bind mobile phone number</button> <button wx:else class="header-icon-btn bg-blue color-fff" bindtap="handleUserInfo">Please click login</button> </block> <block wx:else> <image class="header-icon block" src="{{userData.avatarUrl}}"></image> <view class="color-fff">{{userData.nickName}}</view> </block> </view> js code: handleUserInfo() { wx.getUserProfile({ desc: 'Used to improve member information', // Declare the purpose of obtaining the user's personal information, which will be displayed in the pop-up window later. Please fill in carefully success: (res) => { console.log(res) if (res.errMsg === 'getUserProfile:ok') { this.setData({ userParam: res }) } else { this.setData({ islogin: true }); } } }) }, getPhoneNumber(e) { wx.showLoading({ title: 'Loading', }) wx.cloud.callFunction({ name: 'userInfo', data: { method: 'POST', param: { ...this.data.userParam, }, weRunData: wx.cloud.CloudID(e.detail.cloudID), // Here is the data of mobile phone number }, }) .then(res => { wx.hideLoading() console.log(res) const data = { role: res.result.role, openid: res.result.openid, moblie: res.result.moblie, ...res.result.userInfo } this.setData({ islogin: false, userData: data }); wx.setStorageSync('UserInfo', data) }) },
Here, because friends are registered companies and can pass wechat authentication, the dimension of mobile phone number is added when users register. You can modify the logic when running the project. The user information interface code is posted below, which looks more convenient.
// Cloud function entry file const cloud = require('wx-server-sdk') cloud.init() const db = cloud.database({ env: cloud.DYNAMIC_CURRENT_ENV, // This is a variable that uses the default environment ID }) // Cloud function entry function exports.main = async (event, context) => { const wxContext = cloud.getWXContext() switch (event.method) { case "GET": // Here is the logic to get the user data list if (event.param.moblie) { return db.collection('user_info') .where({ moblie: event.param.moblie, }).skip(event.param.page * event.param.size).limit(event.param.size).get() // skip is the logic for paging } return db.collection('user_info') .skip(event.param.page * event.param.size).limit(event.param.size).get() break; case "POST": const moblie = event.weRunData.data.phoneNumber; let role = 'others' const userInfo = db.collection('user_info') // Here is the user role information configured to distinguish the roles of administrators and users return db.collection('role_info') .get().then((res) => { res.data.map((item, index) => { if (item.openid === wxContext.OPENID) { //It is determined according to the openid after user registration role = item.role } }) const userItem = userInfo.where({ openid: wxContext.OPENID }).get().then(res => { // Here, first judge whether the user information exists if (res.data.length === 0) { console.log('------add') userInfo.add({ data: { ...event.param, openid: wxContext.OPENID, appid: wxContext.APPID, unionid: wxContext.UNIONID, create: new Date(), update: new Date(), role: role, moblie } }) } else { console.log('------update') userInfo.where({ openid: wxContext.OPENID }).update({ data: { ...event.param, openid: wxContext.OPENID, appid: wxContext.APPID, unionid: wxContext.UNIONID, update: new Date(), role: role, moblie } }) } console.log('userItem-------', res) }) return { ...event.param, openid: wxContext.OPENID, appid: wxContext.APPID, unionid: wxContext.UNIONID, role: role, moblie } }) break; default: return { ...event.param, openid: wxContext.OPENID, appid: wxContext.APPID, unionid: wxContext.UNIONID, } break; } }
Order submission
// pages/confirmOrder/index.js Page({ /** * Initial data of the page */ data: { detail: {}, userInfo: {} }, /** * Life cycle function -- listening for page loading */ onLoad: function (options) { let userInfo = wx.getStorageSync('UserInfo'); this.setData({ detail: JSON.parse(options.item), userInfo }) }, /** * Users click the upper right corner to share */ onShareAppMessage: function () { }, formSubmit(e) { console.log(e) const formData = e.detail.value; let flag = false for (const key in formData) { if (formData[key]) { flag = true } else { flag = false } } if (flag) { wx.showLoading({ title: 'Reservation in progress', }) delete this.data.detail._id wx.cloud.callFunction({ // Here, the cloud function of order is called to submit the order name: 'orderInfo', data: { method: 'POST', param: { orderStatus: "PENDING", ...formData, ...this.data.userInfo, ...this.data.detail } }, }).then(res => { console.log(res) wx.hideLoading() wx.navigateTo({ url: '/pages/orderResult/index', }) }) } else { wx.showToast({ title: 'Please complete the information~', icon: 'none' }) } } })
Code of orderinfo cloud function:
// Cloud function entry file const cloud = require('wx-server-sdk') cloud.init() const db = cloud.database({ env: cloud.DYNAMIC_CURRENT_ENV, }) exports.main = async (event, context) => { const wxContext = cloud.getWXContext() const orderInfo = db.collection('order_info') switch (event.method) { case "GET": if (event.param.orderStatus === "ALL") { return orderInfo .where({ openid: wxContext.OPENID, }).orderBy('create', 'desc').skip(event.param.page * event.param.size).limit(event.param.size).get() } return orderInfo .where({ openid: wxContext.OPENID, orderStatus: event.param.orderStatus }).orderBy('create', 'desc').skip(event.param.page * event.param.size).limit(event.param.size).get() break; case "POST": // Here is the logic for submitting orders // delete event.method console.log(event.param) if (event.param._id) { return orderInfo .where({ _id: event.param._id }).update({ data: { orderStatus: event.param.orderStatus, } }) } return orderInfo .add({ data: { ...event.param, create: new Date() } }) break; default: return orderInfo .get() break; } }
Order list
pages/orderInfo/index getOrderInfo(status = "ALL") { //Get interface data wx.showLoading({ title: 'Loading', }) wx.cloud.callFunction({ name: 'orderInfo', data: { method: 'GET', param: { orderStatus: status, ...this.data.pageParam // Paging parameters } }, }).then(res => { wx.hideLoading() const arr = this.data.orderList.concat(res.result.data) this.setData({ orderList: arr, onBottom: res.result.data.length === 0 || false }) }) }, handleLower() { //Modify paging parameters const pageParam = this.data.pageParam; const index = this.data.activeTab pageParam.page++ this.setData({ pageParam }) if (!this.data.onBottom) { this.getOrderInfo(this.data.tabs[index].status) } },
The above two codes are mainly used to complete the function of order query, followed by the query and paging code of order cloud development:
// Cloud function entry file const cloud = require('wx-server-sdk') cloud.init() const db = cloud.database({ env: cloud.DYNAMIC_CURRENT_ENV, }) exports.main = async (event, context) => { const wxContext = cloud.getWXContext() const orderInfo = db.collection('order_info') switch (event.method) { case "GET": if (event.param.orderStatus === "ALL") { return orderInfo .where({ openid: wxContext.OPENID, }).orderBy('create', 'desc').skip(event.param.page * event.param.size).limit(event.param.size).get() } return orderInfo .where({ openid: wxContext.OPENID, orderStatus: event.param.orderStatus }).orderBy('create', 'desc').skip(event.param.page * event.param.size).limit(event.param.size).get() // Here is the paging logic of cloud development break; case "POST": // delete event.method console.log(event.param) if (event.param._id) { return orderInfo .where({ _id: event.param._id }).update({ data: { orderStatus: event.param.orderStatus, } }) } return orderInfo .add({ data: { ...event.param, create: new Date() } }) break; default: return orderInfo .get() break; } }
Click here to view the API s related to cloud development
epilogue
Because the project is relatively small, we don't post a lot of code to waste everyone's valuable time. It is strongly recommended that you run the clone code by yourself. The effect will be much better than reading the article and saying that you don't practice for a long time. This article is mainly to let you try the cloud development model to expand the technology stack and let you master some knowledge points of the back-end.
And everyone's encouragement is the driving force for my next update. Later update plan: use RN and fluent to translate and write the applet, and still do the APP in combination with the cloud development of the applet 🎉🎉🎉
Attach the project address again (optical shop)
There is also a cloud development project I wrote. I want to recycle the local dialect. Compared with this project, you can also try cloud development with the clone project: Localized recycling applet