It's time to master the cloud development of applets ~

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

Keywords: Javascript Mini Program

Added by skippence on Fri, 07 Jan 2022 06:10:54 +0200