微信小程序云开发入门实践

简介: 微信小程序云开发入门实践

云开发介绍

什么是云开发

2017年微信小程序发布后,一度的开发模式是前端页面使用微信小程序的相关组件,在涉及到后台登录及业务交互的时候,需要使用自建的服务器,后台不管是PHP还是JAVA架构,都需要暴露相应的接口供微信小程序调用,这种开发模式技术架构复杂,开发调试难度大,适合本身业务比较成熟的专业公司使用。

之后随着技术的发展,微信推出了云开发的模式,前端还是使用微信的相关组件开发,但是后端通过微信搭建的NodeJS后台,只需要将相应的业务逻辑封装成函数,供前端调用即可,数据库使用MongoDB,可以在线的创建集合、数据库记录,使用起来非常方便。而且因为前后端技术都用微信自建的技术,所以不需要租用第三方服务器,程序可以自动完成部署,上线通过微信官方代码审核后只需要按照使用的流量交费即可,就和手机的卡一样,开通多少钱的月租就会有多少流量。而且前期有个免费流量,一般的应用开通每月100元的月租即可,整体从开发到运维都非常方便。

如何开通云开发

先需要访问微信公众号的官方地址:https://mp.weixin.qq.com/,自己注册一个账号

在主体选择的页面选择小程序

因为是需要通过邮箱注册的,邮箱也是日后登录的账号,按照要求操作就可以了

每次登录的时候需要注册的时候的管理员的微信号码认证一下,通过后就可以打开小程序的后台管理页面了

日常经常使用的功能是版本管理和用户管理,版本管理是代码提交之后可以设置为体验版本,那么在用户管理的体验人员就可以用手机体验你做的小程序的具体效果。用户管理主要是用来增加体验人员的,当然还可以设置开发人员,总之这两个功能是挺好用的。

环境搭建

除了后台的日常操作外,像JAVA开发都会有开发工具一样,微信小程序开发也有自己的开发工具,在后台导航栏的文档栏目下边的工具里可以下载安装

具体安装就不介绍了,非常简单,按照提示一路下一步就行。

创建项目

工具安装完毕后,双击图标,就可以打开了,这里要强调一个知识点就是APPID,这个呢相当于小程序的唯一标识码,日常创建工程的时候都需要填写,怎么找这个ID呢,在后台打开开发栏目:

即可找到。

安装完毕后双击安装后的图标

在打开的界面点击+号创建项目

选择项目需要新建的目录,录入项目名称,最重要的是填写自己项目的APPID,后端服务选择小程序云开发

点击新建按钮即可创建云开发的项目

界面整体功能比较清晰,分为导航栏,左侧的模拟器,和右边的代码管理器

导航栏的云开发相当于数据库管理的后台入口,点击可以进入管理界面创建集合增加记录,同时可以管理小程序上传的附件。编译器可以清除缓存,选择编译哪个页面。而模拟器的作用是显示程序运行后在手机的效果,代码管理器按照文件夹的形式管理不同业务模块的代码。

在代码管理器里分为两部分,前端代码和后端代码,前端代码都放在miniprogram文件夹下,后端代码都放在cloudfunctions文件夹下。

本教程为实践教程,后续会以一个实际的小项目来讲解一下如何使用云开发的技术来开发一款小程序。

需求分析

项目背景

项目的发起方是长期从事教育行业的资深从业者,为了满足家长快速的找到适合的老师进行一对一的辅导,有了搭建家教平台的需求,为此提出项目需求。

家长需求

首页用于介绍“名师汇➸家教帮帮”小程序的宗旨。具体内容如下,可用一个静态HTML把下面内容编好就行:

培优名师:可以按照九宫格显示学科的科目,点击科目可以列出该科目下的所有老师,再点击老师名称可以看到教师的详细信息。

快速请家教,家长可以发布自己的预约信息,填写自己的要求和实际的位置,便于平台匹配合适的老师。

平台管理的功能

老师管理的功能:可以维护老师的信息,发布到培优名师栏目。

预约管理的功能:可以查看最新的预约信息,列表要区分哪些信息被查看过。

数据库设计

通过需求分析,总体上设计了三个表,一个是权限表,里边添加管理员的openid这样就可以在手机上区分是管理员还是普通的家长。第二个表设计了教师表,满足家长浏览信息及管理员维护信息的需要。第三个表设计了预约信息表,记录家长提交的预约内容。

权限表(admin)

教师表(teacher)

预约表(subscribe)

总体架构

要编制项目在看完需求并完成数据库设计之后,下一步就需要考虑技术架构,前端用什么架构、后端用什么架构,这里我们前端采用的是微信的原生前端框架weui,后端是采用的云函数。好处是全部采用微信的框架去搭建省去了各种技术不融合的麻烦,而且开发效率也比较高。

weui搭建方法

登录到微信公众号平台,点击文档栏目

点击扩展能力可以看到weui的组件库

里边介绍的非常详细,初学遇到的问题就是不会安装npm,具体的安装方法是打开开发工具,在miniprogram右键选择在终端打开即可

在终端里依次执行npm init

npm init install

npm install weui-miniprogram

之后在开发工具的详情里勾选使用npm模块

然后在工具栏里选择构建npm

构建成功后多了一个miniprogram_npm目录就代表成功了

构建完毕需要在app.wxss里的第一行增加

@import ‘miniprogram_npm/weui-miniprogram/weui-wxss/dist/style/weui.wxss’;这样weui就可以正常使用了

PS:如果提示npm不是内部或外部命令,说明你电脑没有安装nodejs,自己下载最新的版本安装一下就可以。

首页

首页基本上为展示信息,当初考虑使用微信的richtext组件开发,但是主页的内容老改,每次一调整内容得在js里改半天,后来改成了article组件。

wxml代码

<view class="page">
  <view class="page__hd">
    <view class="weui-article">
      <view class="weui-article__h1 h1_center"><text class="bgindent">名师帮帮</text></view>
    </view>
    <view class="weui-article__section">
      <view class="weui-article__h2 title">概述</view>
      <view class="weui-article__section">
        <view class="weui-article__p p_indent">
          <text class="bgindent">“名师帮帮”</text>何老师从事教学工作二十多年,积累了丰富的教学经验和大量的教师资源,同时也感受到家长、学生的需求与资源匮乏之间的矛盾,希望可以借助该平台在学生和老师之间搭建起一座桥梁。
        </view>
      </view>
      <view class="weui-article__h2 title">教师资质</view>
      <view class="weui-article__section">
        <view class="weui-article__p p_indent">
        <text class="bgindent">“名师帮帮”</text>确认的所有老师都是<text class="green">专职的优秀老师</text>(包括一线在职老师和自由老师),均具有丰富的教学经验,<text class="green">验证过辅导成绩证明</text>,分为:
        </view>
        <view class="weui-article__p p_indent">
        1)<text class="green">培优名师</text>:带出过考入清华北大、获得国内国际竞赛大奖或者班级第一名学生的老师。
        </view>
        <view class="weui-article__p p_indent">
         2)<text class="green">补差名师</text>:辅导后孩子单科学习成绩提高三十分以上的老师。
        </view>
      </view>
      <view class="weui-article__h2 title">运行机制</view>
      <view class="weui-article__section">
        <view class="weui-article__p p_indent">
          <text class="bgindent">“名师帮帮”</text>的运行机制如下:
          <view>
          1). 家长提供学生的学习情况,由何老师推荐适合的最佳老师;
          </view>
          <view>
          2). 上课方式可以到家上课,也可双方协商;
          </view>
          <view>
          3). 课费一次一付给上课老师;
          </view>
          <view>
          4). 何老师负责跟踪教学过程,协助家长和学生解决问题。
          </view>
        </view>
      </view>
      <view class="weui-article__h2 title">课费标准</view>
      <view class="weui-article__section">
        <view class="weui-article__p p_indent">
          <text class="bgindent">“名师帮帮”</text>的老师课时(1小时)费用范围为 300~1000元,具体课费根据年级、科目以及上课时间商议而定。
        </view>
      </view>
      <view class="weui-article__h2 title bgindent">联系人:何老师</view>
      <view class="weui-article__section">
        <view class="weui-article__p">
          1) <text class="green">电话</text>:  
          <view>
          (周一至周五10:00-15:00可电话,其余时间请微信)
          </view>
          <view>
          2) <text class="green">微信</text>:
          </view>
        </view>
      
      </view>
    </view>
  </view>
</view>

wxss

page {
  background: #ffffff;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  padding:5px;
  color:#128b68;
}
.bg{
  padding-right:10px;
}
.h1_center{
  text-align: center;
  
}
.bgindent{
  background: linear-gradient(to right,#005343,#60501d,#802e00,#82181c);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.green{
  color:#43853b;
  font-weight:bold;
}
.weui-article{
  padding-top:0px;
  padding-bottom:0px;
}
.p_indent{
  text-indent: 2em;
}
.title{
  border-left: 3px solid #c60;
  padding-left:15px;
  text-shadow: #f7bc9c 1px 0 10px;
}

导航页

教员速查主要是显示可以开展培训的科目,目前是九个科目,点击某一个科目可以跳转到对应科目的教师列表,这里采用了weui的九宫格布局,在wxml页面里的每个类目绑定类目名称,跳转到列表页的时候传递类目名称

WXML

<view class="page">
    <view class="page__hd">
        <view class="page__title"><text class="bgindent">教员速查</text></view>
    </view>
    <view class="page__bd">
        <view class="weui-grids">
            <block wx:for="{{classes}}" wx:key="*this">
                <navigator url="../teacherlist/teacherlist?name={{item}}&type=0" class="weui-grid" hover-class="weui-grid_active">
                    <image class="weui-grid__icon" src="/images/class-0{{index+1}}.png" />
                    <view wx:if="{{index==0||index==1||index==2||index==6||index==7||index==8}}" class="weui-grid__label blue">{{item}}</view>
                    <view  wx:if="{{index==3||index==4||index==5}}" class="weui-grid__label green">{{item}}</view>
                </navigator>
            </block>
        </view>
    </view>
</view>

WXSS

page{
  background: #ffffff;
}
.title{
  padding:20px;
  color:#F8AD00
}
.item{
  width:100px;
  text-align: center;
  margin-top:25px;
}
.wrap{
  flex-wrap:wrap
}
.bgindent{
  background: linear-gradient(to right,#005343,#60501d,#802e00,#82181c);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.green{
  color:#43853b;
  font-weight:bold;
}
.blue{
  color:#128b68;
  font-weight:bold;
}

js

Page({
  /**
   * 页面的初始数据
   */
  data: {
    classes: ['语文', '数学', '英语', '历史', '地理', '政治', '化学', '物理','生物']
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
  },
  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
  },
  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {
  },
  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {
  },
  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {
  },
  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {
  },
  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {
  }
})

教师列表页

教师列表页需要从数据库中查询符合条件的教师显示到页面中,点击教师的姓名可以跳转到详情页中

wxml

<view class="page">
  <view class="page__bd">
    <view class="weui-panel weui-panel_access">
      <view class="weui-panel__hd"><text class="bgindent">名师汇</text></view>
      <view class="weui-panel__bd">
        <view class="weui-media-box weui-media-box_text" wx:for="{{teacherlist}}">
          <navigator url="../teacherdetail/teacherdetail?id={{item._id}}">
            <view class="weui-media-box__title weui-media-box__title_in-text"><text class="blue">{{item.name}}</text> <text class="blue margin25">编号:</text><text class="green">{{item.no}}</text></view>
            <view class="weui-media-box__desc"><text class="blue">科目:</text> <text class="green">{{item.course}}</text> <text class="blue margin20">性别:</text><text class="green">{{item.sex}} </text><text class="blue margin20">教龄:</text><text class="green">{{item.year}}</text></view>
          </navigator>
        </view>
        <view wx:if="{{teacherlist.length==0}}" style="text-align:center;line-height:20px;font-size:16px;padding-top:25px;padding-bottom:25px">
     <text class="blue">该类别下暂无教师</text>
  </view>
      </view>
    </view>
  </view>
</view>

wxss

.margin20{
  margin-left: 20px;
}
.margin25{
  margin-left: 27px;
}

js

// miniprogram/pages/teacherlist/teacherlist.js
wx.cloud.init()
const db = wx.cloud.database()
const teacherCollection = db.collection('teacher')
const _ = db.command
Page({
  /**
   * 页面的初始数据
   */
  data: {
    teacherlist:[],
    type:""
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    console.log(options.name+" "+options.type)
    console.log(teacherCollection)
    teacherCollection.where({
      course:options.name,
    }).get().then(res => {
        console.log(res.data)
      this.setData({
        teacherlist: res.data,
        type:options.type
      })
      })
  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
  },
  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
  },
  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {
  },
  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {
  },
  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {
  },
  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {
  },
  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {
  }
})

教师详情页

详情页比较简单,接收页面传入的ID参数,然后去数据库获取该教师的信息展示到页面中即可

wxml

<view class="page">
    <view class="page__bd">
<view class="weui-cells weui-cells_after-title">
            <view class="weui-cell">
                <view class="weui-cell__bd"><text class="blue">姓名</text></view>
                <view class="weui-cell__ft"><text class="green">{{teacher.name}}</text></view>
            </view>
            <view class="weui-cell">
                <view class="weui-cell__bd"><text class="blue">编号</text></view>
                <view class="weui-cell__ft"><text class="green">{{teacher.no}}</text></view>
            </view>
            <view class="weui-cell">
                <view class="weui-cell__bd"><text class="blue">科目</text></view>
                <view class="weui-cell__ft"><text class="green">{{teacher.course}}</text></view>
            </view>
            <view class="weui-cell">
                <view class="weui-cell__bd"><text class="blue">性别</text></view>
                <view class="weui-cell__ft"><text class="green">{{teacher.sex}}</text></view>
            </view>
            <view class="weui-cell">
                <view class="weui-cell__bd"><text class="blue">教龄(年)</text></view>
                <view class="weui-cell__ft"><text class="green">{{teacher.year}}</text></view>
            </view>
            <view class="weui-cell">
                <view class="weui-cell__bd"><text class="blue">可辅导年级</text></view>
                <view class="weui-cell__ft"><text class="green">{{teacher.grade}}</text></view>
            </view>
            <view class="weui-cell flex">
                <view class="weui-cell__bd left" style="width:100%"><text class="blue">过往辅导成绩</text></view>
                <view class="weui-cell__ft left" style="width:100%"><text class="green">{{teacher.score}}</text></view>
            </view>
            <view class="weui-cell">
                <view class="weui-cell__bd"><text class="blue">课时费</text></view>
                <view class="weui-cell__ft"><text class="green">{{teacher.cost}}</text></view>
            </view>
        </view>
    </view>
</view>

wxss

.flex{
  flex-direction: column;
  
}
.left{
text-align: left;
}

js

wx.cloud.init()
const db = wx.cloud.database()
const teacherCollection = db.collection('teacher')
const _ = db.command
Page({
  /**
   * 页面的初始数据
   */
  data: { 
    teacher:[]
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    console.log(options.id)
     teacherCollection.doc(options.id).get({
      success: res => {
        console.log(res.data)
        this.setData({
          teacher:res.data
        })
      }
     })
    
  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
  },
  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
  },
  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {
  },
  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {
  },
  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {
  },
  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {
  },
  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {
  },
  getUserInfo: function (result) {
    console.log("111")
    wx.redirectTo({
      url: '../order/order',
    })
  }
})

我的页面

我的页面相对复杂一些,因为第一步需要解决的是登录的问题,微信通过button组件增加属性支持点击按钮之后进行登录,获取到登录信息的时候需要获取该用户是否是管理员,如果不是则下边的菜单看不到教师管理和预约管理的功能,如果是管理员就可以维护教师和处理预约的信息,当然了实现这些功能肯定是需要写云函数的,因为只是小程序端的代码是无法完成的。

wxml

<view class="container">
  <view class="page-body">
    <view class="page-section">
      <view class="page-section-spacing">
        <view style="flex-direction:row;width:100%;">
        <block wx:if="{{userInfo.nickName}}">
        <view class="flex-item"><image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>{{Object.keys(userInfo).length}}</view>
          <view style="text-align:center;margin-bottom:5px">{{userInfo.nickName}}</view>
          </block>
    <block wx:else>
    <view class="flex-item"><image class="userinfo-avatar" src="../../images/user-unlogin.png" background-size="cover"></image></view>
          <view style="text-align:center;margin-bottom:5px"><button open-type="getUserInfo" lang="zh_CN" size="mini" type="primary" bindgetuserinfo="onGotUserInfo">登录{{Object.keys(userInfo).length}}</button></view>
    </block>
          <mp-cells title="">
            <mp-cell link url="../orderlist/orderlist" hover value="我的预约" footer="" ext-class="green">
                <image slot="title" src="../../images/dingdan.png" style="margin-right: 16px;vertical-align: middle;width:20px; height: 20px;"></image>
            </mp-cell>
            <mp-cell link url="../order/order" hover value="快速预约" footer="" ext-class="green">
                <image slot="title" src="../../images/yuyue.png" style="margin-right: 16px;vertical-align: middle;width:20px; height: 20px;"></image>
            </mp-cell>
            <mp-cell wx:if="{{userInfo.isadmin==1}}" link url="../teachermanage/teachermanage" hover value="教师管理" footer="" ext-class="blue">
                <image slot="title" src="../../images/jiaoshiguanli.png" style="margin-right: 16px;vertical-align: middle;width:20px; height: 20px;"></image>
            </mp-cell>
            <mp-cell wx:if="{{userInfo.isadmin==1}}" link url="../ordermanage/ordermanage" hover value="预约管理" footer="" ext-class="blue">
                <image slot="title" src="../../images/jiazhang.png" style="margin-right: 16px;vertical-align: middle;width:20px; height: 20px;"></image>
            </mp-cell>
        </mp-cells>
        </view>
      </view>
    </view>
  </view>
</view>

wxss

.container{
  background: #ffffff;
  width:100%;
  
}
.page-body{
  width:100%;
}
.flex-item{
  text-align: center;
  width:325px;
}

js

// miniprogram/pages/my/my.js
const db = wx.cloud.database()
const admin = db.collection('admin')
const app = getApp();
Page({
  /**
   * 页面的初始数据
   */
  data: {
    userInfo:{}
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
  
    const userInfo = app.globalData.userInfo
    if (userInfo) {
    admin.where({
      openid:userInfo.openid
    }).count().then(res => {
      userInfo.isadmin = res.total
      
        this.setData({
          userInfo: userInfo
        })
     
    })
      .catch(err => {
        console.error(err)
      })
  }
    
   
    /*wx.getSetting({
      success: res => {
        console.log("-----" + res.authSetting['scope.userInfo'])
        if (res.authSetting['scope.userInfo']) {
          // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
          console.log("已授权" + res.authSetting['scope.userInfo'])
          wx.getUserInfo({
            success: res => {
              this.setData({
                avatarUrl: res.userInfo.avatarUrl,
                userInfo: res.userInfo
              })
              console.log(Object.keys(this.data.userInfo).length)
            }
          })
        }
      }
    })*/
    
  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
  },
  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
    const userInfo = app.globalData.userInfo
    if (userInfo) {
    admin.where({
      openid: userInfo.openid
    }).count().then(res => {
        userInfo.isadmin = res.total
        this.setData({
          userInfo: userInfo
        })
      
    })
      .catch(err => {
        console.error(err)
      })
    }
  },
  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {
  },
  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {
  },
  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {
    const userInfo = app.globalData.userInfo
    if (userInfo) {
      admin.where({
        openid: userInfo.openid
      }).count().then(res => {
        userInfo.isadmin = res.total
        this.setData({
          userInfo: userInfo
        })
      })
        .catch(err => {
          console.error(err)
        })
    }
  },
  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {
  },
  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {
  },
  onGotUserInfo: function (result) {
    wx.cloud.callFunction({
      name: 'login',
      success: res => {
        console.log(res.result.dbResult.total)
        result.detail.userInfo.openid = res.result.OPENID
        result.detail.userInfo.isadmin = res.result.dbResult.total
        app.globalData.userInfo = result.detail.userInfo
        this.setData({
          userInfo: result.detail.userInfo
        })
        wx.setStorageSync("userInfo", result.detail.userInfo)
      }
    })
  }
})

预约列表页面主要从数据库查询记录,当预约信息查看后同时更新状态,将状态变更为已读

wxml

<view class="page">
    <view class="page__bd">
        <mp-cells ext-class="my-cells" title="预约列表">
        <block wx:for="{{subscribe}}">
        <navigator url="../orderdetail/orderdetail?id={{item._id}}&flag=1">
             <block wx:if="{{item.status=='0'}}">
                <mp-cell ext-class="blue" value="预约科目:{{item.class}}[未读]" footer="{{item.createtime}}"></mp-cell>
              </block>
              <block wx:if="{{item.status=='1'}}">
                 <mp-cell ext-class="green" wx:if="{{item.status==='1'}}" value="预约科目:{{item.class}}[已读]" footer="{{item.createtime}}"></mp-cell>
                </block>
              
                </navigator>
          </block>
        </mp-cells>
    </view>
</view>

json

{
  "usingComponents": {
    "mp-cells": "../components/cells/cells",
    "mp-cell": "../components/cell/cell",
    "mp-slideview": "../components/slideview/slideview"
  }
}

wxss

/* miniprogram/pages/ordermanage/ordermanage.wxss */
.weui-cell__ft{
color:#43853b!important;
} 
.weui-cells__title{
  color:#43853b;
}

js

wx.cloud.init()
const db = wx.cloud.database()
const subscribeCollection = db.collection('subscribe')
const _ = db.command
const app = getApp();
Page({
  data: {
    subcribe: {}
  },
  onLoad: function () {
    
    subscribeCollection.orderBy('createtime', 'desc').get().then(res => {
      for (var index in res.data) {
        var time = res.data[index].createtime;
        console.log(time)
        res.data[index].createtime = time.getFullYear() + "-" + (time.getMonth() + 1) + "-" + time.getDate()
      }
      this.setData({
        subscribe: res.data,
      })
    })
    this.setData({
      slideButtons: [{
        type: 'warn',
        text: '删除',
        extClass: 'test',
        src: '/page/weui/cell/icon_del.svg', // icon的路径
      }],
    });
  },
  onShow(){
    subscribeCollection.orderBy('createtime', 'desc').get().then(res => {
      for (var index in res.data) {
        var time = res.data[index].createtime;
        console.log(time)
        res.data[index].createtime = time.getFullYear() + "-" + (time.getMonth() + 1) + "-" + time.getDate()
      }
      this.setData({
        subscribe: res.data,
      })
    })
  },
  slideButtonTap(e) {
    console.log('slide button tap', e.detail)
  }
});

预约新增页面使用了weui的扩展组件,主要使用了表单,可以很方便的进行校验

wxml

<mp-toptips msg="{{error}}" type="error" show="{{error}}"></mp-toptips>
<view class="page" xmlns:wx="http://www.w3.org/1999/xhtml">
    <view class="page__bd">
        <mp-form id="form" rules="{{rules}}" models="{{formData}}">
            <mp-cells class="green" title="快速预约家教">
                <mp-cell prop="class" title="辅导科目" ext-class="blue">
                    <input bindinput="formInputChange" data-field="class" placeholder-class="green" class="weui-input green" placeholder="请输入辅导科目"/>
                </mp-cell>
                <mp-cell prop="grade" title="辅导年级" ext-class="blue">
                    <input bindinput="formInputChange" data-field="grade" placeholder-class="green" class="weui-input green" placeholder="请输入辅导年级"/>
                </mp-cell>
                <mp-cell prop="contactname" title="联系人姓名" ext-class="blue">
                    <input bindinput="formInputChange" data-field="contactname" placeholder-class="green" class="weui-input green" placeholder="请输入联系人姓名"/>
                </mp-cell>
                <mp-cell prop="telphone" title="手机号" ext-class="blue">
                    <input placeholder-class="green" bindinput="formInputChange" data-field="telphone" class="weui-input green" placeholder="请输入手机号"/>
                </mp-cell>
                <mp-cell  title="微信号" ext-class="blue">
                    <input placeholder-class="green" bindinput="formInputChange" data-field="microno" class="weui-input green" placeholder="请输入微信号"/>
                </mp-cell>
            </mp-cells>
            <view class="weui-cells__title blue">地址</view>
        <view class="weui-cells weui-cells_after-title">
            <view class="weui-cell">
                <view class="weui-cell__bd">
                    <input placeholder-class="green" class="weui-input green" bindinput="formInputChange" placeholder="填写辅导的详细地址" data-field="address"/>
                </view>
            </view>
        </view>
        <view class="weui-cells__title blue">要求</view>
        <view class="weui-cells weui-cells_after-title">
            <view class="weui-cell">
                <view class="weui-cell__bd">
                    <textarea placeholder-class="green" data-field="demand" bindinput="formInputChange" class="weui-textarea green"  placeholder="填写您对辅导老师的具体要求" style="height: 3.3em" />
                </view>
            </view>
        </view>
        <view class="weui-btn-area">
            <button class="weui-btn" type="primary" bindtap="submitForm">提交</button>
        </view>
        </mp-form>
        
    </view>
</view>

wxss

/* miniprogram/pages/order/order.wxss */
.weui-cells__title{
   color:#43853b;
}

js

wx.cloud.init()
const db = wx.cloud.database()
const orderCollection = db.collection('subscribe')
const _ = db.command
Component({
  data: {
    showTopTips: false,
    formData: {
    },
    rules: [{
      name: 'class',
      rules: { required: true, message: '辅导科目是必选项' },
    }, {
        name: 'grade',
        rules: { required: true, message: '辅导年级是必选项' },
      }, {
        name: 'contactname',
        rules: { required: true, message: '联系人姓名是必选项' },
      }, {
        name: 'telphone',
        rules: [{ required: true, message: '手机号必填' }, { mobile: true, message: '手机号格式不对' }],
      }, {
        name: 'microno',
        rules: { required: true, message: '微信号是必选项' },
      }]
  },
  methods: {
    formInputChange(e) {
      const { field } = e.currentTarget.dataset
      this.setData({
        [`formData.${field}`]: e.detail.value
      })
    },
    submitForm() {
      this.selectComponent('#form').validate((valid, errors) => {
        console.log('valid', valid, errors)
        if (!valid) {
          const firstError = Object.keys(errors)
          if (firstError.length) {
            this.setData({
              error: errors[firstError[0]].message
            })
          }
        } else {
          console.log(this.data.formData)
          var address ="";
          var demand = ""; 
            if(this.data.formData.hasOwnProperty('address')){
            address = this.data.formData.address;
            console.log(address)
          }
          if (this.data.formData.hasOwnProperty('demand')){
            demand = this.data.formData.demand;
          }
          orderCollection.add({
            // data 字段表示需新增的 JSON 数据
            data:{
              class:this.data.formData.class,
              grade:this.data.formData.grade,
              contactname:this.data.formData.contactname,
              telphone:this.data.formData.telphone,
              microno:this.data.formData.microno,
              address:address,
              demand:demand,
              createtime: new Date(),
              status:0
            }
          })
            .then(res => {
              console.log(res)
              wx.showToast({
                title: '预约成功',
                icon: 'success',
                duration: 2000
              })
              wx.switchTab({
                url: '../my/my',
              })
            })
            .catch(console.error)
        }
      })
    }
  }
});

json

{
  "usingComponents": {
    "mp-toptips": "../components/toptips/toptips",
    "mp-cells": "../components/cells/cells",
    "mp-cell": "../components/cell/cell",
    "mp-checkbox": "../components/checkbox/checkbox",
    "mp-checkbox-group": "../components/checkbox-group/checkbox-group",
    "mp-form": "../components/form/form"
  }
}

课程总结

本次课程通过一个实际的案例演示了如何使用微信云开发的技术去开发一款小程序,总体上微信小程序云开发非常的快,很容易上手,而且不用部署服务器节约了非常多的时间,最主要的特别适合个人开发,一个人就可以满足日常商业中常见的需求,实现中小微企业业务的快速上云,快快实验一下吧。

项目源码

https://gitee.com/tuodagitee/famous-teacher-help.git

线上地址请在微信小程序搜索名师帮帮查看最终效果

相关文章
|
2月前
|
存储 JSON 小程序
微信小程序入门之新建并认识小程序结构
微信小程序入门之新建并认识小程序结构
53 1
|
2月前
|
监控 小程序 前端开发
小程序全栈开发中的WebSocket实时通信实践
【10月更文挑战第3天】随着移动互联网的发展,小程序因便捷的用户体验和社交传播能力,成为企业拓展业务的新渠道。本文探讨了小程序全栈开发中的WebSocket实时通信实践,包括其实时通信、长连接及双向通信的特点,并通过实时聊天、推送、游戏和监控等功能的实现,展示了WebSocket在小程序中的应用。开发者需注意安全性、性能及兼容性等问题,以保障小程序的稳定运行和用户体验。
50 7
|
2月前
|
XML 小程序 JavaScript
小程序入门之项目配置说明和数据绑定
小程序入门之项目配置说明和数据绑定
41 1
|
2月前
|
小程序 开发工具
微信小程序云开发的开通
微信小程序云开发的开通
48 0
微信小程序云开发的开通
|
4月前
|
小程序 前端开发 Java
SpringBoot+uniapp+uview打造H5+小程序+APP入门学习的聊天小项目
JavaDog Chat v1.0.0 是一款基于 SpringBoot、MybatisPlus 和 uniapp 的简易聊天软件,兼容 H5、小程序和 APP,提供丰富的注释和简洁代码,适合初学者。主要功能包括登录注册、消息发送、好友管理及群组交流。
109 0
SpringBoot+uniapp+uview打造H5+小程序+APP入门学习的聊天小项目
|
2月前
|
小程序 前端开发 JavaScript
小程序入门之认识view和text组件
小程序入门之认识view和text组件
81 0
|
4月前
|
存储 运维 小程序
后端开发零负担!揭秘支付宝小程序云开发的高效与安全,你的项目也能飞速上线?
【8月更文挑战第27天】支付宝小程序云开发是由阿里云提供的集成开发环境,助力开发者高效、安全地构建小程序后端服务,免去服务器搭建,显著提高开发效率并降低运维成本。它集成了云函数、云数据库及云存储等功能,便于快速搭建后端逻辑。例如,仅需简单几行代码即可创建HTTP接口或进行数据管理。这使得开发者能更专注于业务逻辑和用户体验优化,同时平台还提供了强大的安全保障措施,确保数据安全和用户隐私。无论对于初创团队还是成熟企业,支付宝小程序云开发都能有效提升产品迭代速度和市场竞争力。
86 1
|
4月前
|
存储 小程序 数据可视化
小程序开发问题之使用小程序云服务开发个人相册小程序如何解决
小程序开发问题之使用小程序云服务开发个人相册小程序如何解决
|
4月前
|
监控 小程序 安全
小程序全栈开发中的WebSocket实时通信实践是一种高效的开发模式。
随着移动互联网的发展,小程序成为企业拓展业务的新渠道。WebSocket作为一种实时通信协议,可在小程序中实现如实时聊天、推送、游戏等功能。它支持客户端与服务器间的全双工长连接通信,优于传统HTTP。开发者需注意安全、性能及兼容性等问题,以优化体验并保障稳定运行。掌握WebSocket有助于提升小程序功能性与用户体验。
50 1
|
4月前
|
缓存 小程序 定位技术
深度剖析:支付宝小程序走向成功的关键要素和实践路径
【8月更文挑战第27天】随着移动互联网的发展,小程序已成为各大平台不可或缺的一部分。支付宝小程序凭借其强大的生态系统和便捷服务脱颖而出。本文将通过案例和代码分析成功的支付宝小程序的打造过程:首先注重良好的用户体验,包括简洁的界面设计与快速响应;充分利用支付宝的功能如支付和地理位置服务吸引用户;进行性能优化如合理代码结构和缓存机制提升运行效率;采取精准营销策略增加用户关注度;并持续更新优化以适应市场变化和用户需求。
77 0