性格测评小程序08测评功能搭建

发布于:2025-02-19 ⋅ 阅读:(27) ⋅ 点赞:(0)


我们已经用7篇的篇幅介绍了测评小程序的基础功能搭建,包括用户注册、登录以及题库的后台管理功能。就像盖楼一样,地基打好之后我们就可以往高盖了。测评小程序的核心功能是答题的功能,本篇我们先搭建一下答题功能。

1 答题功能需求分析

答题有如下功能

  • 要有一个进度条,显示当前的答题进度,进度条旁边显示当前是第几题、总共有多少题
  • 要可以显示题目和选项
  • 选项可以选择
  • 要有上一题和下一题的功能可以继续和回退

2 页面设计

我们的答题功能先要有一个引导页可以进入,为了后续功能的扩展,我们使用宫格导航的布局结构搭建首页
在这里插入图片描述
怎么说呢,凡是测评类的其实只是起一个心里按摩的功能,因为人处在纷繁变化的世界中,任何测评工具都不足以将人划分到某一个类别里。只不过在你比较迷茫的时候,给予一定心里疏导的功能。

点击功能菜单的时候我们进入到具体的答题页面

在这里插入图片描述

3 搭建后端API

答题功能相对来说是有一定复杂度的,首先我们看一下我们原来在搭建后台时候的表结构

题库表
在这里插入图片描述
题库表存储着每一道题的题干信息,这里有一个注意的地方是有一个题目选项,这个字段是平台自动添加的。在子表如果添加关联关系,主表会自动添加一个子表的数组字段。

选项表
在这里插入图片描述
选项表存储着每一个题目的选项信息。如果按照传统开发的思路,我们肯定是要做表关联,这样将主表和子表合并成为一行用来在界面上显示。

微搭作为低代码工具,并不需要主动的构造表关联,平台早就帮我们做好了封装,我们使用API来直接获取数据。点击侧边栏的API,点击+号创建API
在这里插入图片描述
选择自定义代码
在这里插入图片描述
输入方法名称和标识
在这里插入图片描述
贴入如下代码

module.exports = async function (params, context) {
  const result = await context.callModel({
      name: "Questions",
      methodName: "wedaGetRecordsV2",
      params: {
        // 筛选内容,当前筛选的含义为:名字为 "juli" 或者 "foo"
        // 返回字段选择
        orderBy: [
          {
            qno: "asc", // 创建时间,正序
          }
        ],
        select: {
          content: true, // 常见的配置,返回主表
          dimension:true,
          qno:true,
          options:{_id:true,xx:true,score:true,content:true}
        },
        // 返回total字段
        getCount: true,
        // 页面大小
        pageSize: 10,
        // 当前页面
        pageNumber: 1,
      },
    });
// 替换规则
const dimensionMap = {
  "1": "EL",
  "2": "SN",
  "3": "TF",
  "4": "SP",
};

const optionMap = {
  "1": "A",
  "2": "B",
  "3": "C",
  "4": "D",
};

// 替换逻辑
result.records.forEach(record => {
  // 替换 dimension
  if (dimensionMap[record.dimension]) {
    record.dimension = dimensionMap[record.dimension];
  }

  // 替换 options 的 xx 值
  record.options.forEach(option => {
    if (optionMap[option.xx]) {
      option.xx = optionMap[option.xx];
    }
  });
});
  // 这里返回数据,和出参结构映射
  return result;
};

如果在读取主表字段的时候也要一并读取子表的信息,我们可以在选择字段的时候,将子表的字段一并选出,关键是在select的配置

select: {
          content: true, // 常见的配置,返回主表
          dimension:true,
          qno:true,
          options:{_id:true,xx:true,score:true,content:true}
        }

这里的options就是我们主表的对应字段
在这里插入图片描述
默认他只存储了_id,我们可以将其余的字段一并列出

代码的第二部分就是处理枚举项,我们主表的维度是枚举项,子表的选项也是枚举项,通过循环语句将枚举项变成实际的值,这样方便程序后续展示和处理

代码贴入之后,点击方法测试,可以看到结果
在这里插入图片描述
点击出参自动映射就完成了我们API的编写

4 搭建页面

按照我们上边页面的结构进行搭建,首先我们将页面分为三个部分,分别用来显示进度条、选项、按钮
在这里插入图片描述
第一部分的普通容器里我们放置进度条组件和文本组件,来搭建我们的顶部内容
在这里插入图片描述
他的容器部分要设置布局,设置为横向排列,这样让进度条和文本在一行显示
在这里插入图片描述
第二部分内容,我们显示的是题干和选项
在这里插入图片描述
用文本组件来显示题干的内容,单选组件用来显示选项的内容

第三部分就是显示按钮了
在这里插入图片描述
好多学初学者不知道该如何搭建布局。你可以理解为你要怎么设计你的房子,比如我们这个就设计了三个屋子,每个屋子用普通容器来表示。每间屋子根据功能不同要放置不同的家具,比如卧室通常我们放置床和衣柜,而客厅通常是放置沙发和电视。

5 创建变量

布局搭建好之后,如何让数据显示出来呢?通常我们是通过变量来存储和显示数据。变量有两种,一种是我们自己赋值的,叫自定义变量。一种是通过数据库来读取数据的叫数据查询

API创建好之后需要在页面上读取显示,先创建一个外部API查询
在这里插入图片描述
然后选择我们的API名称和方法名称,就是我们刚刚创建的API
在这里插入图片描述
这里注意我们的变量是选择的手动执行,因为我们要在页面加载的时候才调用

之后就是程序控制显示时需要的变量,第一个记录我们当前的题号,类型是数字
在这里插入图片描述
第二个记录当前的题目信息,包含题干和选项信息,类型是对象
在这里插入图片描述
第三个记录我们的所有的题目信息,类型是数组
在这里插入图片描述
第四个记录题目的总数,类型是数字
在这里插入图片描述

6 自定义方法

变量定义好之后,就是具体的页面逻辑了。首先要定义一个方法用来初始化数据,我们命名为load方法
在这里插入图片描述
代码如下:

export default async function ({ event, data }) {
    try {
        const loadQuestions = await $w.getQuestions.trigger();
        console.log("loadQuestions", loadQuestions);

        const total = loadQuestions?.total || 0;
        console.log("total", total);

        if (total > 0) {
            $w.page.dataset.state.totalQuestion = total;
            $w.page.dataset.state.questions = loadQuestions.records || [];
            $w.page.dataset.state.currentIndex = 0; // 初始为第一题
            $w.page.dataset.state.question = $w.page.dataset.state.questions[0] || null;
            console.log("question", $w.page.dataset.state.question);
        } else {
            console.error("No questions found.");
            $w.utils.showToast({
                title: "未加载到题目数据",
                icon: "error",
                duration: 2000,
            });
        }
    } catch (error) {
        console.error("Error loading questions:", error);
        $w.utils.showToast({
            title: "加载题目失败",
            icon: "error",
            duration: 2000,
        });
    }
}

代码的逻辑是先从API中加载数据,然后赋值给我们创建好的自定义变量

接着创建下一题的方法,用来显示下一个题目信息
在这里插入图片描述
代码如下:

export default function ({ event, data }) {
    const state = $w.page.dataset.state;
    const currentIndex = state.currentIndex || 0;
    const totalQuestions = state.totalQuestion || 0;
    if(!$w.radio1.value){
        $w.utils.showToast({
            title: "请选择答案",
            icon: "error",
            duration: 1000,
        });
        return
    }

    // 保存当前题目的用户答案
    state.questions[currentIndex].userAnswer = $w.radio1.value;

    if (currentIndex + 1 < totalQuestions) {
        state.currentIndex += 1;
        state.question = state.questions[state.currentIndex];
        $w.radio1.clearValue()
         // 回填用户答案(如果有)
        if (state.questions[state.currentIndex].userAnswer) {
            $w.radio1.setValue(state.questions[state.currentIndex].userAnswer);
        }

        console.log("Next question:", state.question);
    } else {
        $w.utils.showToast({
            title: "已经是最后一题",
            icon: "error",
            duration: 1000,
        });
    }
}

其实下一题的逻辑是很简单的,只是从数组中获取下一个元素的内容而已

既然有下一题,我们就还需要有上一题的功能
在这里插入图片描述
代码如下:

export default function ({ event, data }) {
    const state = $w.page.dataset.state;
    const currentIndex = state.currentIndex || 0;

    if (currentIndex > 0) {
        state.currentIndex -= 1;
        state.question = state.questions[state.currentIndex];
        // 清空选项
        $w.radio1.clearValue();

        // 回填用户答案(如果有)
        if (state.questions[state.currentIndex].userAnswer) {
            $w.radio1.setValue(state.questions[state.currentIndex].userAnswer);
        }
        console.log("Previous question:", state.question);
    } else {
        $w.utils.showToast({
            title: "已经是第一题",
            icon: "error",
            duration: 1000,
        });
    }
}

上一题的核心逻辑是在数组里取前一个位置的数据

7 数据绑定及事件绑定

变量和方法都创建好之后,就是我们低代码的最后一步操作,绑定了。首先需要给进度条绑定数据,进度条先需要知道进度值,用来显示当前是第几题
在这里插入图片描述

$w.page.dataset.state.currentIndex+1

接着要配置一共有多少题
在这里插入图片描述

$w.page.dataset.state.totalQuestion

进度条旁边的文本组件,我们用来显示当前第几题和总题数,用表达式进行绑定
在这里插入图片描述

`${$w.page.dataset.state.currentIndex+1}/${$w.page.dataset.state.totalQuestion}`

之后给我们的题干绑定数据,使用表达式进行绑定
在这里插入图片描述

$w.page.dataset.state.question.qno+"."+$w.page.dataset.state.question.content

之后给单选绑定数据,也是使用表达式进行绑定
在这里插入图片描述

$w.page.dataset.state.question.options.map(option=>({
  label:option.xx+" "+option.content,
  value:option._id
}))

最后呢就是给按钮绑定事件了
在这里插入图片描述
加载数据的时候要配置加载时机,我们在页面显示的时候调用
在这里插入图片描述

总结

本篇我们介绍了测评功能的搭建过程,低代码开发基本就是三板斧,搭建组件,定义变量和绑定事件。至于如何进行布局,创建哪些变量,要怎么写方法,就需要你结合业务场景进行拆解和组装,这块也是低代码开发的难点,需要通过各种场景的练习不断地精进。


网站公告

今日签到

点亮在社区的每一天
去签到