问卷调查类小程序

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

最近需要工作写个小程序,这里记录一下期间学习的框架,以及遇到的各种问题,也供大家参考。


一、小程序框架

小程序自身分为两个主要部分独立运行:view 模块和 service 模块。在开发者工具中,它们独立运行于不同的 webivew tag 中。

view 模块负责前端界面显示,它由 wxml 和 wxss 转换后代码以及微信提供相关辅助模块组成。 一个 view 模块对应一个 页面, 小程序支持同时多个 view 存在。
service 模块负责后台逻辑,它由 js 代码以及微信提供的相关辅助模块组成。 一个应用只有一个 service 进程,它同样也是一个页面。它在程序生命周期内后台运行,service 模块通过与 view 模块实现不同但接口格式一样的微信JSBridge 对象跟后台通信。

在这里插入图片描述

具体内容详见下文,这里不再展开。:

https://blog.csdn.net/liyanfang1004/article/details/103735429?utm_medium=distribute.wap_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.wap_blog_relevant_pic&depth_1-utm_source=distribute.wap_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.wap_blog_relevant_pic

二、开发过程

1.工具准备

小程序需要使用微信开发者工具来进行开发,同时最常用的参考文档是微信小程序官方文档。在开发者工具中包含了模拟器、调试器等,内容很全面。也可以用云模式来在腾讯云进行后台开发。使得开发者不用搭建数据库等,专注于逻辑设计,简化后台设计

另外为了更好的展示小程序可以用一些工具插件,例如wx-chartsecharts等,这两个都可用于图形化展示统计数据。

2.开发程序

小程序一般包括主程序、pages、componets、images、style等文件夹。如下图所示,app.js、app,wxss等是主程序。pages文件夹内都是页面程序,其中默认第一个页面是index。如果涉及到云开发还包含cloudfunction文件夹,不过云功能主要是写后台API。
在这里插入图片描述
我这里举的例子需求是做一个支持在线随堂考试的小程序,能够收集学生的答案自动判分,并给老师呈现学生的成绩情况。

页面设计主要包含2个内容:1个是提供给学生的界面,主要用于在线测试;第二个则给老师,用于显示学生的成绩情况。在线测试的页面放在index下,给老师的页面放在managerSatis下,下面拣重点介绍一下。

inde文件夹下包含index.wxml, index.js, index.json, index.wxss。其中index.wxml描述了界面,index.js是页面逻辑程序,index.wxss定义了页面内容的格式, index.json可以包含使用的插件情况。以下是程序主要代码部分:

index.xml:

<view class="page-body">
  <view class="page-section">
    <view class="title_postion">
      <view class="title_view"> 随堂测试题</view>
    </view>
  </view>

  <view class="page-section">
    <view class="weui-cells_title">
      <text class="page-section-title-im">*</text> 
        <text class="cls3-a"> 请填写姓名</text> 
    </view>
        <view class="weui-cell weui-cell_input">
          <input class="label" auto-focus bindinput="bindNameInput" placeholder="请填写姓名"/>
        </view>
    </view>
.....

    <view class="page-section page-section-gap">
      <text>\n</text>
      <text>\n</text>
      <view class="page-section-title">
        <text class="page-section-title-im">*</text> 
        <text class="cls3-a">1 农药残留不包括以下哪种?</text> 
      </view>
        <radio-group bindchange="items1RadioChange">
            <view class="label" wx:for="{{items1}}">
              <radio  value="{{item.value}}" ></radio>
              <label class="label-1-text" ><text>{{item.name}}</text></label>
           </view>
        </radio-group>
      </view>
....
    <view class="button-sp-area">
      <button class="btn1" wx:if = '{{notSubmit}}' bindtap="submit"> 提交 </button>
    </view>    

    <view class="button-manager">
      <button class="btn1" wx:if = '{{authority}}' bindtap="managerSwitch"> 查询结果 </button>
    </view>    

这里主要包含了单选、文本填写和按钮。其中单选主要用radio组件,多选可以用checkbox组件

index.js

在这里插入代码片Page({
  data: {
    avatarUrl: './user-unlogin.png',
    userInfo: {},
    logged: false,
    authority: false,
    takeSession: false,
    notSubmit: true,
    requestResult: '',
    result:0,
    name: '',
    num: '',
    items1: [
      {name: '农药原体', value: 'A'},
      {name: '有毒代谢物', value: 'B',checked: 'true'},
      {name: '防腐剂', value: 'C'},
      {name: '降解产物', value: 'D'}
    ],
   ....
  },
    onLoad: function() {
    this.authentication();
  },
  items1RadioChange(e) {
    console.log('radio发生change事件,携带value值为:', e.detail.value)

    const items = this.data.items1
    this.answer_data.items1 = e.detail.value
    for (let i = 0, len = items.length; i < len; ++i) {
      items[i].checked = items[i].value === e.detail.value
      if(items[i].checked === true)
      {
        this.answer_data.items1Name = items[i].name
      }
    }

    this.setData({
       items1:items
    })
  },
  ...
  authentication: function () {
   
    wx.cloud.callFunction({
      name: 'login',
      complete: res => {
        console.log('res值为:', res.result)
        const db = wx.cloud.database()
        db.collection('author').get().then(res2=>{
            console.log('res2值为:', res2.data);
            if (res.result.openid === res2.data[0].openid) {
              this.setData({
                authority: true
              })
            }
        }) 
 
      }
    })
  },
  bindNameInput: function (e) {
      this.data.name = e.detail.value
  },
...
submit(e) 
  {
    if (this.answer_data.items1 === this.result_date.items1){
      this.data.result += 10
    }

   .... 

    const db = wx.cloud.database()
    db.collection('test').add({
      data: {
        num: this.data.num,
        name: this.data.name,
        result: this.data.result
      },
      success(res) {

        wx.showModal({
          content: '已提交成功,禁止再提交。',
        })

      },
      fail(res) {
        wx.showToast({
          icon: 'none',
          title: '新增记录失败'
        })
        console.error('[数据库] [新增记录] 失败:', err)
      }
    }) 
    this.setData({
      notSubmit: false
    })
  },
  
  managerSwitch(e)
  {
    wx.redirectTo({
      url: '../managerSatis/managerSatis',
     })
    }

这里需要注意以下方面: 1 可以通过this.setData可以动态改变页面的数据。 2 authentication部分代码需要在云数据库端新建author数据库,并将管理者openid保存到author数据库中,这样管理者登录时可以通过openid的对比,可以改变authority值,在wxml中采用 wx:if = '{{authority}}',因此只有管理者才可以看到最后的统计结果。注意,这里提交了默认云函数的login函数,才能实现该功能。

关于index.wxss就不详细展开了,感兴趣的读者可以参见所提供的代码。

managerSatis部分主要是统计学生分数情况,采用了echars插件实现动态图像显示,以下是主要部分:

  1. 显示不同分数段的学生百分比;
  2. 显示数据库中每个学生的情况

managerSatis.xml:

<!--miniprogram/pages/managerSatis/managerSatis.wxml-->
<view class="page-body">

    <view style='position:relative;width:100%;height:600rpx;'>
      <ec-canvas id="mychartOne" canvas-id="mychart-bar" ec="{{ecOne}}"></ec-canvas>
    </view>
    <text class="a"  > \n </text> 
    <view class='a' wx:for="{{cloudData}}">
    <view >序号{{index+1}}:{{item.name}} \t {{item.num}} \t {{item.result}}</view>
    <text class="a"  > \n </text> 
</view>
    
    <view class="button-manager">
      <button class="btn1"  bindtap="updateResult"> 更新结果 </button>
    </view>  
</view>

managerSatis.js:

import * as echarts from '../../components/ec-canvas/echarts';
var Chart = null;
Page({

  /**
   * 页面的初始数据
   */
  data: {
    num100: 0,
    num90To100:0,
    num80To90:0,
    num70To80:0,
    num60To70:0,
    num60:0,
    cloudData:[],
    ec:{
      lazyLoad:true
    },
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    const db = wx.cloud.database();
    const _ = db.command
    db.collection('test').where({
      result: _.lt(60)
    }).count({
      //如果查询成功的话
      success: res => {
        console.log("信息查询:",res.total)
        this.setData({
          num60: res.total
        })
        console.log("信息查询6011111111111:",this.data.num60)
        
      }
    })
   ....

    wx.cloud.callFunction({
      // 云函数名称
      name: 'sendData',
      // 传给云函数的参数
      success: res => {
        console.log(res) // 3
        this.setData({
          cloudData: res.result.data
        })
      },
      fail: console.error
    })

     this.ecComponentOne = this.selectComponent('#mychartOne');
     this.init_echarts();
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {

  },

  init_echarts:function(){
          this.ecComponentOne.init((canvas, width, height) =>{
             Chart = echarts.init(canvas, null, {
                width: width,
                height: height
             });  
             Chart.setOption(this.getOption());
             Chart.on('click', function(handler, context){
            });
             return Chart;
          });
  },

  getOption: function () {
    var that=this;
    console.log("进入了getOption方法中!")
    
    var option = {
      backgroundColor: "#ffffff",
      color: ["#da8982", "#ec9683","#45B580","#b6e4c7","#B9C753","#dbce8e"],
      series: [{
        label: {
          normal: {
            show: true,
            formatter: ' {b} \n {c} ',//({ d } %)  b=名称 c=数值 d=百分比 \n换行 
            fontSize: 12,
            fontWeight:700,
          }
        },
        labelLine: { show: true },
        type: 'pie',//饼图实例
        center: ['50%', '55%'], //圆饼图的位置
        radius: [0, '60%'], //圆饼图大小的比例
        data: [{
          value: this.data.num60,
          name: '60分以下',
        }
        ..... 
         ],
        itemStyle: {
          emphasis: {
            shadowBlur: 10,
            shadowOffsetX: 0,
            shadowColor: 'rgba(0, 2, 2, 0.3)'
          }
        }
      }]
    };
    return option;
  },

  updateResult(){
   
    const db = wx.cloud.database();
    const _ = db.command
    db.collection('test').where({
      result: _.lt(60)
    }).count({
      //如果查询成功的话
      success: res => {
        console.log("信息查询:",res.total)
        this.setData({
          num60: res.total
        })
      }
    })

   ......
    Chart.setOption(this.getOption());
    Chart.on('click', function(handler, context){
   });
  }
})

该部分以下功能需要注意:

  1. 采用调用sendData的方式,接收云数据库中所有的感兴建的数据。如果仅在小程序前端采用查询函数只能推送10条所有消息。
  2. 采用echarts统计不同分数段学生数,主要通过Chart.setOption(this.getOption());这句来动态改变图形的取值。echarts可以实现动态的画图数据更新,wx-charts插件只能实现静态画图。

其中云函数sendData的代码如下:
managerSatis.js:

// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init()
const db = cloud.database()
const test = db.collection('test')
// 云函数入口函数
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()

  const MAX_LIMIT = 100
  const countResult = await test.count()
  const total = countResult.total
  // 计算需分几次取
  const batchTimes = Math.ceil(total / 100)
  // 承载所有读操作的 promise 的数组
  const tasks = []
  for (let i = 0; i < batchTimes; i++) {
    const promise = test.skip(i * MAX_LIMIT).limit(MAX_LIMIT).get()
    tasks.push(promise)
  }
  // 等待所有
  return (await Promise.all(tasks)).reduce((acc, cur) => ({
    data: acc.data.concat(cur.data),
    errMsg: acc.errMsg,
  }))
}

该函数主要实现了将数据库中数据发送给小程序前端的功能。
具体所有的代码详见示例程序, 该代码能够成功部署并使用。

总结

腾讯的小程序系统还是对开发者非常友好的,能够支持快速实现各种应用。在开发过程中包括了体验版和正式版,其中正式版需要经过审查确认。

  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值