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

server/2025/2/21 12:19:45/

目录

  • 1 答题功能需求分析
  • 2 页面设计
  • 3 搭建后端API
  • 4 搭建页面
  • 5 创建变量
  • 6 自定义方法
  • 7 数据绑定及事件绑定
  • 总结

我们已经用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 => {// 替换 dimensionif (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
}))

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

总结

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


http://www.ppmy.cn/server/169191.html

相关文章

项目2 数据可视化--- 第十五章 生成数据

数据分析是使用代码来探索数据内的规律和关联。 数据可视化是通过可视化表示来 探索和呈现数据集内的规律。 好的数据可视化&#xff0c;可以发现数据集中未知的规律和意义。 一个流行的工具是Matplotlib&#xff0c;他是一个数据绘图库&#xff1b; 还有Plotly包&#xff…

MyBatis-Plus之通用枚举

MyBatis-Plus之通用枚举 前言 MyBatis-Plus中提供了通用枚举&#xff0c;简单来说就是将数据库中的某一字段的代替的含义转换成真实的含义将数据展示给用户&#xff0c;用户在存储时也会将真实值转换成代替的数字存入到数据库中。举个例子&#xff1a;用户性别在数据库中存储…

Java 大视界 -- 企业数字化转型中的 Java 大数据战略与实践(93)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

【深度学习】计算机视觉(CV)-目标检测-DETR(DEtection TRansformer)—— 基于 Transformer 的端到端目标检测

1.什么是 DETR&#xff1f; DETR&#xff08;DEtection TRansformer&#xff09; 是 Facebook AI&#xff08;FAIR&#xff09;于 2020 年提出的 端到端目标检测算法&#xff0c;它基于 Transformer 架构&#xff0c;消除了 Faster R-CNN、YOLO 等方法中的 候选框&#xff08;…

IM聊天系统架构实现

一、IM系统整体架构 二、企业级IM系统如何实现心跳与断线重连机制&#xff1b; 1、重连机制&#xff08;服务端下线&#xff09; 服务端下线&#xff0c;客户端netty可以感知到&#xff0c;在感知的方法中进行重连的操作&#xff0c;注意重连可能连接到旧的服务器继续报错&…

深入解析iOS视频录制(二):自定义UI的实现

深入解析 iOS 视频录制&#xff08;一&#xff09;&#xff1a;录制管理核心MWRecordingController 类的设计与实现 深入解析iOS视频录制&#xff08;二&#xff09;&#xff1a;自定义UI的实现​​​​​​​ 深入解析 iOS 视频录制&#xff08;三&#xff09;&#xff1a;完…

【物联网】电子电路基础知识

文章目录 一、基本元器件1. 电阻2. 电容3. 电感4. 二极管(1)符号(2)特性(3)实例分析5. 三极管(1)符号(2)开关特性(3)实例6. MOS管(产效应管)(1)符号(2)MOS管极性判定(3)MOS管作为开关(4)MOS管vs三极管7. 门电路(1)与门(2)或门(3)非门二、常用元器件…

嵌入式面试高频面试题:嵌入式系统调试方法大全

目录 调试基础概述 调试的重要性 嵌入式系统特点 调试流程 硬件调试方法 JTAG 调试 仿真器调试 逻辑分析仪 软件调试技巧 断点调试 日志输出 内存监视 代码静态分析 嵌入式调试器 常用调试器介绍 调试器使用技巧 远程调试方法 串口调试 网络调试 特殊调试场…