微信小程序答题信息如何更改(手把手教你开发一个答题微信小程序)
微信小程序答题信息如何更改(手把手教你开发一个答题微信小程序)修改test.js/**app.wxss**/ .container { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: space-between; padding: 200rpx 0; box-sizing: border-box; }  .bc_green{ background-color: #09BB07; } .bc_red{ background-color: #F76260; } .bc_blue{ background-color: #10AEFF; } .bc_yellow{ background-color: #FFBE00; } .bc_gray{ background-c
部分项目截图





开发试题分类页面
新增home页面
pages目录下新建home目录,并添加4个文件,如图所示:

其中: home.js
// pages/home/home.js
Page({
  data: {
  } 
  onLoad: function (options) {
  } 
  toTestPage: function(e){
   let testId = e.currentTarget.dataset['testid'];
   wx.navigateTo({
    url: '../test/test?testId=' testId
   })
  }
})
    
home.wxml
<!--pages/home/home.wxml-->
<view class="page">
  <view class="page-title">请选择试题:</view>
  <view class="flex-box">
   <view class="flex-item"><view class="item bc_green" bindtap="toTestPage" data-testId="18">IT知识</view></view>
   <view class="flex-item"><view class="item bc_red" bindtap="toTestPage" data-testId="15">游戏知识</view></view>
   <view class="flex-item"><view class="item bc_yellow" bindtap="toTestPage" data-testId="21">体育知识</view></view>
   <view class="flex-item"><view class="item bc_blue" bindtap="toTestPage" data-testId="27">动物知识</view></view>
   <view class="flex-item item-last"><view class="item bc_green" bindtap="toTestPage" data-testId="0">综合知识</view></view>
  </view>
</view>
    
home.json
{
  "navigationBarTitleText": "试题分类" 
  "usingComponents": {}
}
    
home.wxss
/* pages/home/home.wxss */
.page-title {
  padding-top: 20rpx;
  padding-left: 40rpx;
  font-size: 16px;
}
.flex-box {
  display: flex;
  align-items:center;
  flex-wrap: wrap;
  justify-content: space-between;
  padding: 20rpx;
  box-sizing:border-box;
}
.flex-item {
  width: 50%;
  height: 200rpx;
  padding: 20rpx;
  box-sizing:border-box;
}
.item {
  width:100%;
  height:100%;
  border-radius:8rpx;
  display: flex;
  align-items:center;
  justify-content: center;
  color: #fff;
}
.item-last {
  flex: 1;
}
    
修改app.json,注意:pages/home/home一定要放到pages数组的最前,以成为首页。
{
  "pages": [
   "pages/home/home" 
   "pages/index/index" 
   "pages/logs/logs" 
  ] 
  "window": {
   "backgroundTextStyle": "light" 
   "navigationBarBackgroundColor": "#fff" 
   "navigationBarTitleText": "WeChat" 
   "navigationBarTextStyle": "black"
  } 
  "style": "v2" 
  "sitemapLocation": "sitemap.json"
}
    
修改app.wxss,定义全局样式
/**app.wxss**/
.container {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 200rpx 0;
  box-sizing: border-box;
} 
.bc_green{
   background-color: #09BB07;
}
.bc_red{
   background-color: #F76260;
}
.bc_blue{
   background-color: #10AEFF;
}
.bc_yellow{
   background-color: #FFBE00;
}
.bc_gray{
   background-color: #C9C9C9;
}
运行结果

开发试题展示功能
新增test页面
pages目录下新建test目录,并添加4个文件,如图所示:

修改test.js
// pages/test/test.js
Page({
  /**
  * 页面的初始数据
  */
  data: {
   test_id:0
  } 
  /**
  * 生命周期函数--监听页面加载
  */
  onLoad: function (options) {
   this.setData({test_id:options.testId})
  }
    })
    
修改test.wxml
<!--pages/test/test.wxml-->
<text>我是{{test_id}}</text>
运行结果
在试题分类页点击某一分类,跳转到试题页,试题页显示分类id

Mock试题数据
项目目录下新增data目录,data目录新增json.js,存放我们的试题模拟数据。
var json = {
  "18": [
    {
      "question": "This mobile OS held the largest market share in 2012.?" 
      "option": {
        "A": "iOS" 
        "B": "Android" 
        "C": "BlackBerry" 
        "D": "Symbian"
      } 
      "true": "A" 
      "scores": 10 
      "checked": false
    } 
    {
      "question": "This mobile OS held the largest market share in 2012.?" 
      "option": {
        "A": "iOS" 
        "B": "Android" 
        "C": "BlackBerry" 
        "D": "Symbian"
      } 
      "true": "A" 
      "scores": 10 
      "checked": false
    }
  ] 
  "0": [
    {
      "question": "This mobile OS held the largest market share in 2012.?" 
      "option": {
        "A": "iOS" 
        "B": "Android" 
        "C": "BlackBerry" 
        "D": "Symbian"
      } 
      "true": "A" 
      "scores": 10 
      "checked": false
    } 
    {
      "question": "This mobile OS held the largest market share in 2012.?" 
      "option": {
        "A": "iOS" 
        "B": "Android" 
        "C": "BlackBerry" 
        "D": "Symbian"
      } 
      "true": "A" 
      "scores": 10 
      "checked": false
    }
  ]
}
module.exports = {
  questionList: json
}
    
修改app.js
var jsonList = require('data/json.js');
App({
...
  } 
  globalData: {
    questionList: jsonList.questionList   // 拿到答题数据
    // questionList:{} 
    quizCategory:{
      "0": "综合知识" 
      "18": "IT知识" 
      "21": "体育知识" 
      "15": "游戏知识" 
      "27":"动物知识" 
    }
  }
})
    
修改test.js
// import he from "he";
var app = getApp();
Page({
  data: {
    bIsReady: false  // 页面是否准备就绪
    index: 0   // 题目序列
    chooseValue: []  // 选择的答案序列
  } 
  shuffle(array) {
    return array.sort(() => Math.random() - 0.5);
  } 
  /**
   * 生成一个从 start 到 end 的连续数组
   * @param start
   * @param end
   */
  generateArray: function (start  end) {
    return Array.from(new Array(end   1).keys()).slice(start)
  } 
  onLoad: function (options) {
    wx.setNavigationBarTitle({ title: options.testId }) // 动态设置导航条标题
    this.setData({
      questionList: app.globalData.questionList[options.testId]   // 拿到答题数据
      testId: options.testId // 课程ID
    })
    let countArr = this.generateArray(0  this.data.questionList.length - 1); // 生成题序
    this.setData({
      bIsReady: true 
      shuffleIndex: this.shuffle(countArr).slice(0  countArr.length) // 生成随机题序 [2 0 3] 并截取num道题
    })
  } 
  /*
  * 单选事件
  */
  radioChange: function (e) {
    console.log('checkbox发生change事件,携带value值为:'  e.detail.value)
    this.data.chooseValue[this.data.index] = e.detail.value;
    console.log(this.data.chooseValue);
  } 
  /*
  * 退出答题 按钮
  */
  outTest: function () {
    wx.showModal({
      title: '提示' 
      content: '你真的要退出答题吗?' 
      success(res) {
        if (res.confirm) {
          console.log('用户点击确定')
          wx.switchTab({
            url: '../home/home'
          })
        } else if (res.cancel) {
          console.log('用户点击取消')
        }
      }
    })
  } 
  /*
  * 下一题/提交 按钮
  */
  nextSubmit: function () {
    // 如果没有选择
    if (this.data.chooseValue[this.data.index] == undefined) {
      wx.showToast({
        title: '请选择至少一个答案!' 
        icon: 'none' 
        duration: 2000 
        success: function () {
          return;
        }
      })
      return;
    }
    // 判断是不是最后一题
    if (this.data.index < this.data.shuffleIndex.length - 1) {
      // 渲染下一题
      this.setData({
        index: this.data.index   1
      })
    } else {
      console.log('ok')
    }
  }
})
    
test.wxml
<!--pages/test/test.wxml-->
<view wx:if="{{bIsReady}}" class="page">
  <!--标题-->
  <view class='page__hd'>
    <view class="page__title">
      {{index 1}}、{{questionList[shuffleIndex[index]].question}}
      ({{questionList[shuffleIndex[index]].scores}}分)
    </view>
  </view>
  <!--内容-->
  <view class="page__bd">
    <radio-group class="radio-group" bindchange="radioChange">
      <label class="radio my-choosebox" wx:for="{{questionList[shuffleIndex[index]].option}}" wx:for-index="key"  wx:for-item="value">
        <radio value="{{key}}" checked="{{questionList[shuffleIndex[index]].checked}}"/>{{key}}、{{value}}
      </label>
    </radio-group>
  </view>
  <!--按钮-->
  <view class='page_ft'>
    <view class='mybutton'>
      <button bindtap='nextSubmit' wx:if="{{index == questionList.length-1}}">提交</button>
      <button bindtap='nextSubmit' wx:else>下一题</button>
      <text bindtap='outTest' class="toindex-btn">退出答题</text>
    </view>
  </view>
</view>
    
test.wxss
/* pages/test/test.wxss */
.page {
  padding: 20rpx;
}
.page__bd {
  padding: 20rpx;
}
.my-choosebox {
  display: block;
  margin-bottom: 20rpx;
}
.toindex-btn {
  margin-top: 20rpx;
  display:inline-block;
  line-height:2.3;
  font-size:13px;
  padding:0 1.34em;
  color:#576b95;
  text-decoration:underline;
  float: right;
}
项目运行结果:

请求真实数据
修改test.js
  getQuestions(testId) {
    // 显示标题栏加载效果
    wx.showNavigationBarLoading();
    wx.request({
      // url: 'https://opentdb.com/api.php?amount=10&difficulty=easy&type=multiple&category='   testId 
      url: 'https://opentdb.com/api.php?amount=10&difficulty=easy&type=multiple&category='   testId 
      method: "GET" 
      success: res => {
        if (res.data.response_code === 0) {
          this.setData({
            questionList: this.parseQuestion(res.data.results)   // 拿到答题数据
            testId: testId // 课程ID
          })
          console.log(this.data.questionList);
          app.globalData.questionList[testId] = this.data.questionList
          let count = this.generateArray(0  this.data.questionList.length - 1); // 生成题序
          this.setData({
            bIsReady: true 
            shuffleIndex: this.shuffle(count).slice(0  10) // 生成随机题序 [2 0 3] 并截取num道题
          })
        } else {
          ;
        }
        // 停止加载效果
        wx.stopPullDownRefresh();
        wx.hideNavigationBarLoading();
      } 
      fail: err => {
        // 停止加载效果
        wx.stopPullDownRefresh();
        wx.hideNavigationBarLoading();
      }
    });
  } 
  onLoad: function (options) {
    this.getQuestions(options.testId)
    console.log(options);
    wx.setNavigationBarTitle({ title: app.globalData.quizCategory[options.testId] }) // 动态设置导航条标题
  } 
    
解析返回的数据:
   // 主题列表数据模型
  parseQuestion(aList) {
    let aTopicList = [];
    if (!aList || (aList && !Array.isArray(aList))) {
      aList = [];
    }
    aTopicList = aList.map(oItem => {
      const answers = [oItem.correct_answer  oItem.incorrect_answers].flat()
      let optionArr = ['A'  'B'  'C'  'D']
      let options = {}
      let optionArrShuffle = this.shuffle(optionArr)
      for (let i = 0; i < answers.length; i  ) {
        options[optionArr[i]] = String(answers[i]);
      }
      const ordered_options = {};
      Object.keys(options).sort().forEach(function (key) {
        ordered_options[key] = options[key];
      });
      return {
        "question": String(oItem.question)  // id
        "scores": 10 
        "checked": false 
        "option": ordered_options 
        "true": optionArr[0]
      };
    });
    return aTopicList;
  } 
    
这里解析的原因是,接口返回的json数据和我们自己设计的数据格式略有不同,我们要转换成自己的数据格式: 接口返回的数据格式:
{
    "response_code": 0 
    "results": [{
        "category": "Science: Computers" 
        "type": "multiple" 
        "difficulty": "easy" 
        "question": "The numbering system with a radix of 16 is more commonly referred to as " 
        "correct_answer": "Hexidecimal" 
        "incorrect_answers": ["Binary"  "Duodecimal"  "Octal"]
    }  {
        "category": "Science: Computers" 
        "type": "multiple" 
        "difficulty": "easy" 
        "question": "This mobile OS held the largest market share in 2012." 
        "correct_answer": "iOS" 
        "incorrect_answers": ["Android"  "BlackBerry"  "Symbian"]
    }  {
        "category": "Science: Computers" 
        "type": "multiple" 
        "difficulty": "easy" 
        "question": "How many values can a single byte represent?" 
        "correct_answer": "256" 
        "incorrect_answers": ["8"  "1"  "1024"]
    }  {
        "category": "Science: Computers" 
        "type": "multiple" 
        "difficulty": "easy" 
        "question": "In computing  what does MIDI stand for?" 
        "correct_answer": "Musical Instrument Digital Interface" 
        "incorrect_answers": ["Musical Interface of Digital Instruments"  "Modular Interface of Digital Instruments"  "Musical Instrument Data Interface"]
    }  {
        "category": "Science: Computers" 
        "type": "multiple" 
        "difficulty": "easy" 
        "question": "In computing  what does LAN stand for?" 
        "correct_answer": "Local Area Network" 
        "incorrect_answers": ["Long Antenna Node"  "Light Access Node"  "Land Address Navigation"]
    }]
}
    
我们自己的数据格式:
var json = {
  "18": [
    {
      "question": "This mobile OS held the largest market share in 2012.?" 
      "option": {
        "A": "iOS" 
        "B": "Android" 
        "C": "BlackBerry" 
        "D": "Symbian"
      } 
      "true": "A" 
      "scores": 10 
      "checked": false
    } 
    {
      "question": "This mobile OS held the largest market share in 2012.?" 
      "option": {
        "A": "iOS" 
        "B": "Android" 
        "C": "BlackBerry" 
        "D": "Symbian"
      } 
      "true": "A" 
      "scores": 10 
      "checked": false
    }
  ] 
  "0": [
    {
      "question": "This mobile OS held the largest market share in 2012.?" 
      "option": {
        "A": "iOS" 
        "B": "Android" 
        "C": "BlackBerry" 
        "D": "Symbian"
      } 
      "true": "A" 
      "scores": 10 
      "checked": false
    } 
    {
      "question": "This mobile OS held the largest market share in 2012.?" 
      "option": {
        "A": "iOS" 
        "B": "Android" 
        "C": "BlackBerry" 
        "D": "Symbian"
      } 
      "true": "A" 
      "scores": 10 
      "checked": false
    }
  ]
}
    
注意:
开发期间:不校验合法域名,web-view.....这里不要勾选。

引入第三方库
细心的朋友可能会发现,有些题目中有乱码,如下图所示':

有一个很好的第三方库He可以处理这个问题。
我们需要使用npm导入一个第三方库处理这个问题,大家会学习到在小程序开发中如何使用npm引入第三方库。
项目根目录下新建package.json文件
{
  "name": "wechatanswer-master" 
  "version": "1.0.0" 
  "description": "答题类微信小程序" 
  "main": "app.js" 
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  } 
  "repository": {
    "type": "git" 
    "url": "https://gitee.com/kamiba/my_quiz_wechat_app.git"
  } 
  "author": "" 
  "license": "ISC" 
  "dependencies": {
    "he": "^1.2.0"
  }
}
    
2、执行npm install --production xxx,这个xxx就是你想使用的npm 包。此时在当前文件夹下会生成一个node_modules文件夹。PS:此处请务必使用--production选项,可以减少安装一些业务无关的 npm 包,从而减少整个小程序包的大小。
npm install --production he
    
3、在微信开发者工具-->工具-->构建npm,此时会生成一个miniprogram_npm文件夹。

4、构建完成后就可以使用 npm 包了。首先把使用npm模块勾起来,然后在js文件中引入即可。

然后修改test.js
import he from "he";
  // 主题列表数据模型
  parseQuestion(aList) {
    let aTopicList = [];
    if (!aList || (aList && !Array.isArray(aList))) {
      aList = [];
    }
    aTopicList = aList.map(oItem => {
      const answers = [oItem.correct_answer  oItem.incorrect_answers].flat()
      let optionArr = ['A'  'B'  'C'  'D']
      let options = {}
      let optionArrShuffle = this.shuffle(optionArr)
      for (let i = 0; i < answers.length; i  ) {
        options[optionArr[i]] = he.decode(String(answers[i]));
      }
      const ordered_options = {};
      Object.keys(options).sort().forEach(function (key) {
        ordered_options[key] = options[key];
      });
      return {
        "question": he.decode(String(oItem.question))  // id
        "scores": 10 
        "checked": false 
        "option": ordered_options 
        "true": optionArr[0]
      };
    });
    return aTopicList;
  } 
    
上面和以前有三处修改
import he from "he";
options[optionArr[i]] = he.decode(String(answers[i]));
"question": he.decode(String(oItem.question))  
计算用户得分,记录错题
修改test.js
Page({
  data: {
    bIsReady: false  // 页面是否准备就绪
    index: 0   // 题目序列
    chooseValue: []  // 选择的答案序列
    totalScore: 100  // 总分
    wrong: 0  // 错误的题目数量
    wrongListSort: []  // 错误的题目集合
  } 
    
 /*
  * 下一题/提交 按钮
  */
  nextSubmit: function () {
    // 如果没有选择
    if (this.data.chooseValue[this.data.index] == undefined) {
      wx.showToast({
        title: '请选择至少一个答案!' 
        icon: 'none' 
        duration: 2000 
        success: function () {
          return;
        }
      })
      return;
    }
    // 判断答案是否正确
    this.chooseError();
    // 判断是不是最后一题
    if (this.data.index < this.data.shuffleIndex.length - 1) {
      // 渲染下一题
      this.setData({
        index: this.data.index   1
      })
    } else {
      let wrongListSort = JSON.stringify(this.data.wrongListSort);
      let chooseValue = JSON.stringify(this.data.chooseValue);
      let shuffleIndex = JSON.stringify(this.data.shuffleIndex);
      console.log('wrongListSort:'   wrongListSort)
      wx.navigateTo({
        url: '../results/results?totalScore='   this.data.totalScore   '&shuffleIndex='   shuffleIndex   '&chooseValue='   chooseValue   '&wrongListSort='   wrongListSort   '&testId='   this.data.testId
      })
      // 设置缓存
      var logs = wx.getStorageSync('logs') || []
      let logsList = { "date": Date.now()  "testId": app.globalData.quizCategory[this.data.testId]  "score": this.data.totalScore }
      logs.unshift(logsList);
      wx.setStorageSync('logs'  logs);
    }
  } 
  /*
* 错题处理
*/
  chooseError: function () {
    var trueValue = this.data.questionList[this.data.shuffleIndex[this.data.index]]['true'];
    var chooseVal = this.data.chooseValue[this.data.index];
    console.log('选择了'   chooseVal   '答案是'   trueValue);
    if (chooseVal.toString() != trueValue.toString()) {
      console.log('错了');
      this.data.wrong  ;
      this.data.wrongListSort.push(this.data.index);
      this.setData({
        totalScore: this.data.totalScore - this.data.questionList[this.data.shuffleIndex[this.data.index]]['scores']  // 扣分操作
      })
    }
  } 
实现结果展示页面

pages目录下新增page---results
results.js
// pages/results/results.js
var app = getApp();
Page({
  data: {
    totalScore: null  // 分数
    shuffleIndex: []  // 错误的题数-乱序
    wrongListSort: []   // 错误的题数-正序
    chooseValue: []  // 选择的答案
    remark: ["好极了!你很棒棒哦"  "哎哟不错哦"  "别灰心,继续努力哦!"]  // 评语
    modalShow: false
  } 
  onLoad: function (options) {
    console.log(options);
    wx.setNavigationBarTitle({ title: app.globalData.quizCategory[options.testId] }) // 动态设置导航条标题
    let shuffleIndex = JSON.parse(options.shuffleIndex);
    let wrongListSort = JSON.parse(options.wrongListSort);
    let chooseValue = JSON.parse(options.chooseValue);
    this.setData({
      totalScore: options.totalScore != "" ? options.totalScore : "无" 
      shuffleIndex: shuffleIndex 
      wrongListSort: wrongListSort 
      chooseValue: chooseValue 
      questionList: app.globalData.questionList[options.testId]   // 拿到答题数据
      testId: options.testId  // 课程ID
    })
    console.log(this.data.chooseValue);
  } 
  // 查看错题
  toView: function () {
    // 显示弹窗
    this.setData({
      modalShow: true
    })
  } 
  // 返回首页
  toIndex: function () {
    wx.switchTab({
      url: '../home/home'
    })
  }
})
    
results.json
{
  "navigationBarTitleText": "WeChatTest" 
  "usingComponents": {
    "wrong-modal":"/components/wrongModal/wrongModal"
  }
}
    
results.wxml
<view class="page">
  <!--标题-->
  <view class='page-head'>
    <view class="page-title">
      答题结束!您的得分为:
    </view>
    <!--分数-->
    <view class='page-score'>
      <text class="score-num">{{totalScore}}</text>
      <text class="score-text">分</text>
    </view>
    <text class="score-remark">{{totalScore==100?remark[0]:(totalScore>=80?remark[1]:remark[2])}}</text>  <!-- 评价 -->
  </view>
  <!--查询错误-->
  <view class='page-footer'>
    <view class="wrong-view" wx:if="{{wrongListSort.length > 0}}">
      <text>错误的题数:</text>
      <text wx:for="{{wrongListSort}}">[{{item-0 1}}]</text> 题
    </view>
    <view class="wrong-btns">
      <button type="default" bindtap="toView" hover-class="other-button-hover" class="wrong-btn" wx:if="{{wrongListSort.length > 0}}"> 点击查看 </button>
      <button type="default" bindtap="toIndex" hover-class="other-button-hover" class="wrong-btn"> 返回首页 </button>
    </view>
  </view>
  <wrong-modal modalShow="{{modalShow}}" shuffleIndex="{{shuffleIndex}}" wrongListSort="{{wrongListSort}}" chooseValue="{{chooseValue}}" questionList="{{questionList}}" testId="{{testId}}"
    ></wrong-modal>
</view>
    
results.wxss
/* pages/results/results.wxss */
.page {
  padding: 20rpx;
}
.page-head {
  text-align: center;
}
.page-title {
}
.page-score {
  display: flex;
  justify-content: center;
  align-items: flex-end;
  padding-top:40rpx;
  padding-bottom:40rpx;
}
.score-num {
  font-size:100rpx;
}
.page-footer {
  margin-top:60rpx;
  text-align: center;
}
.wrong-btns {
  display:flex;
  align-items:center;
  justify-content:center;
  margin-top: 60rpx;
}
.wrong-btn {
  margin-left:20rpx;
  margin-right:20rpx;
  height:70rpx;
  line-height:70rpx;
  font-size:14px;
}
实现错题查看页面

项目目录下新增components目录。components目录下新增wrongModal目录,wrongModal目录下新增page---wrongModal
wrongModal.js
// components/wrongModal/wrongModal.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    // 是否显示
    modalShow: {
      type: Boolean 
      value: false
    } 
    // 题库
    questionList: {
      type: Array 
      value: []
    } 
    // 课程ID
    testId: {
      type: String 
      value: '101-1'
    } 
    // 题库乱序index
    shuffleIndex: {
      type: Array 
      value: []
    } 
    // 错题题数-正序
    wrongListSort: {
      type: Array 
      value: []
    } 
    // 选择的答案
    chooseValue: {
      type: Array 
      value: []
    }
  } 
  /**
   * 组件的初始数据
   */
  data: {
    index: 0 // wrongList的index
  } 
  /**
   * 组件所在页面的生命周期
   */
  pageLifetimes: {
    show: function () {
      // 页面被展示
      console.log('show')
      console.log(this.data.questionList)
      // console.log(this.data.wrongList)
    } 
    hide: function () {
      // 页面被隐藏
    } 
    resize: function (size) {
      // 页面尺寸变化
    }
  } 
  /**
   * 组件的方法列表
   */
  methods: {
    // 下一题
    next: function(){
      if (this.data.index < this.data.wrongListSort.length - 1){
        // 渲染下一题
        this.setData({
          index: this.data.index   1
        })
      }
    } 
    // 关闭弹窗
    closeModal: function(){
      this.setData({
        modalShow: false
      })
    } 
    // 再来一次
    again: function(){
      wx.reLaunch({
        url: '../test/test?testId='   this.data.testId
      })
    } 
    // 返回首页
    toIndex: function () {
      wx.reLaunch({
        url: '../home/home'
      })
    } 
  }
})
    
wrongModal.json
{
  "component": true 
  "usingComponents": {}
}
    
wrongModal.wxml
<!--components/wrongModal/wrongModal.wxml-->
<view class="modal-page" wx:if="{{modalShow}}">
  <view class="modal-mask" bindtap="closeModal"></view>
  <!-- 内容 -->
  <view class="modal-content">
    <view class="modal-title">
      题目: {{questionList[shuffleIndex[wrongListSort[index]]].question}} 
    </view>
    <view class="modal-body">
      <radio-group class="radio-group" bindchange="radioChange">
        <label class="radio my-choosebox" wx:for="{{questionList[shuffleIndex[wrongListSort[index]]].option}}" wx:for-index="key"  wx:for-item="value">
          <radio disabled="{{true}}" value="{{key}}" checked="{{questionList[shuffleIndex[wrongListSort[index]]].checked}}"/>{{key}}、{{value}}
        </label>
      </radio-group>
    </view>
    <!-- 答案解析 -->
    <view class="modal-answer">
      <text class="answer-text wrong-answer">
        您的答案为 {{chooseValue[wrongListSort[index]]}}
      </text>
      <text class="answer-text true-answer">
        正确答案为 {{questionList[shuffleIndex[wrongListSort[index]]]['true']}}
      </text>
    </view>
    <!-- 操作按钮 -->
    <view class="modal-button">
      <view wx:if="{{index == wrongListSort.length-1}}" class="modal-btns">
        <button bindtap='again' class="modal-btn">再来一次</button>
        <button bindtap='toIndex' class="modal-btn">返回首页</button>
      </view>
      <button bindtap='next' wx:else class="modal-btn">下一题</button>
    </view>
  </view>
</view>
    
wrongModal.wxss
/* components/wrongModal/wrongModal.wxss */
.modal-mask {
  position:fixed;
  width:100%;
  height:100%;
  top:0;
  left:0;
  z-index:10;
  background: #000;
  opacity: 0.5;
  overflow: hidden;
}
.modal-page {
  display:flex;
  align-items:center;
  justify-content:center;
  width:100%;
  height:100%;
  top:0;
  position:absolute;
  left:0;
}
.modal-content {
  width: 80%;
  min-height: 80%;
  background: #fff;
  border-radius: 8rpx;
  z-index:11;
  padding: 20rpx;
}
.modal-title {
  font-size: 14px;
}
.modal-body {
  padding: 20rpx;
}
.my-choosebox {
  display: block;
  margin-bottom: 20rpx;
  font-size: 14px;
}
.modal-answer {
  display: flex;
}
.answer-text {
  font-size: 14px;
  margin-right: 20rpx;
}
.modal-button {
  display: flex;
  align-items:center;
  justify-content:center;
  margin-top:60rpx;
}
.modal-btns {
  display: flex;
  align-items:center;
  justify-content:center;
}
.modal-btn {
  margin-left:20rpx;
  margin-right:20rpx;
  height:70rpx;
  line-height:70rpx;
  font-size:12px;
}
实现成绩记录页面

修改项目目录下的app.json,增加底部导航栏

{
  "pages": [
    "pages/home/home" 
    "pages/logs/logs" 
    "pages/test/test" 
    "pages/results/results" 
    "pages/index/index"
  ] 
  "window": {
    "backgroundTextStyle": "light" 
    "navigationBarBackgroundColor": "#fff" 
    "navigationBarTitleText": "WeChat" 
    "navigationBarTextStyle": "black"
  } 
  "tabBar": {
    "color": "#666666" 
    "selectedColor": "#3cc51f" 
    "borderStyle": "black" 
    "backgroundColor": "#ffffff" 
    "list": [
      {
        "pagePath": "pages/home/home" 
        "iconPath": "image/icon_component.png" 
        "selectedIconPath": "image/icon_component_HL.png" 
        "text": "答题"
      } 
      {
        "pagePath": "pages/logs/logs" 
        "iconPath": "image/icon_API.png" 
        "selectedIconPath": "image/icon_API_HL.png" 
        "text": "记录"
      }
    ]
  } 
  "sitemapLocation": "sitemap.json"
}
    
项目目录下新增image文件夹,并添加以下文件,具体文件请下载源码获取:

修改pages目录下logs页面
logs.js
//logs.js
const util = require('../../utils/util.js')
Page({
  data: {
    logs: [] 
  } 
  onShow: function() {
    this.setData({
      logs: this.formatLogs()
    })
  } 
  // 拿到缓存并格式化日期数据
  formatLogs: function(){
    let newList = [];
    (wx.getStorageSync('logs') || []).forEach(log => {
      if(log.date){
        log['date'] = util.formatTime(new Date(log.date));
        newList.push(log);
      }
    })
    return newList;
  }
})
    
logs.json
{
  "navigationBarTitleText": "查看日志" 
  "usingComponents": {}
}
    
logs.wxml
<!--logs.wxml-->
<view class="page">
  <view class="table" wx:if="{{logs.length>0}}">
    <view class="tr bg-w">
      <view class="th first">时间</view>
      <view class="th">试题</view>
      <view class="th ">得分</view>
    </view>
    <block wx:for="{{logs}}" wx:for-item="item">
      <view class="tr">
        <view class="td first">{{item.date}}</view>
        <view class="td">{{item.testId}}</view>
        <view class="td">{{item.score}}</view>
      </view>
    </block>
  </view>
  <view class="no-record" wx:else>
    <image src="/image/wechat.png" class="no-image"></image>
    <text class="no-text">没有数据哦~</text>
  </view>
</view>
    
logs.wxss
.table {
 border: 0px solid darkgray;
 font-size: 12px;
}
.tr {
 display: flex;
 width: 100%;
 justify-content: center;
 height: 2rem;
 align-items: center;
}
.td {
  width:40%;
  justify-content: center;
  text-align: center;
}
.bg-w{
 background: snow;
}
.th {
 width: 40%;
 justify-content: center;
 background: #3366FF;
 color: #fff;
 display: flex;
 height: 2rem;
 align-items: center;
}
.first {
  flex:1 0 auto;
}
.no-record {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.no-image {
  width: 200rpx;
  height: 200rpx;
  margin-top: 200rpx;
  margin-bottom: 40rpx;
}
.no-text {
  font-size: 16px;
  color: #ccc;
  display: block;
}
    
修改test.js
  /*
  * 下一题/提交 按钮
  */
  nextSubmit: function () {
    // 如果没有选择
	.....
      // 设置缓存
      var logs = wx.getStorageSync('logs') || []
      let logsList = { "date": Date.now()  "testId": app.globalData.quizCategory[this.data.testId]  "score": this.data.totalScore }
      logs.unshift(logsList);
      wx.setStorageSync('logs'  logs);
    }
  } 
最终项目结构





