第5章〓豆豆云助教“课程”模块页面开发 数字中国对课程的影响(课程由纸质化走向数字化) 随着互联网、物联网等新技术飞速发展,万物互联化、数据泛在化的大趋势日益明显,数据信息的爆炸性增长态势日趋严峻,能否有效采集、管理、流通、分析、应用数据信息,不但成为驱动全球经济社会发展的关键环节,而且日益成为国家、地区、企业和个人的核心竞争力。 2015年12月,习近平总书记在第二届世界互联网大会开幕式上,首次正式提出推进“数字中国”建设的倡议。2017年10月18日,习近平总书记在中国共产党第十九次全国代表大会的报告中进一步提出“建设科技强国、质量强国、航天强国、网络强国、交通强国、数字中国、智慧社会”,明确了建设数字中国的宏大构想。 数字中国对于课程的影响是全面而深远的,它不仅改变了课程内容和教学方式,还涉及课程管理和学生评估等方面。首先,数字中国的推动使得课程教学资源由纸质化转向数字化。教育机构可以创建在线学习平台、教学网站和教育应用程序,为教师和学生提供丰富的数字教材、课件、视频、模拟实验等教学资源。学生可以通过电子设备和互联网访问这些资源,实现随时随地地学习。 其次,数字中国为课程提供了数据分析和个性化教育的机会。学生在数字化学习过程中产生大量数据,这些数据可以被收集、分析和应用于个性化教育。通过数据分析技术,教师可以深入了解学生的学习情况和需求,根据学生的差异性提供个性化的教学方案和反馈。同时,数字中国的发展推动了远程教育和在线学习的普及。通过数字技术和互联网平台,学生可以在不受地域限制的情况下进行高质量的课程学习。远程教育和在线学习提供了更多的学习机会,使得学习更加灵活和便捷,同时也促进了终身学习的理念。 总体而言,数字中国对教育行业的影响是全方位的,它改变了教育的传统方式和范式,提供了更多的学习资源和工具,促进了教育的个性化和创新发展。本章我们也将顺应数字中国的风向,引入“线上课程”模块的开发,在之前开发的tabBar中除了“我的”页面以外,添加一栏“主页面”,也就是本章开发的“课程”模块,主要包括“课程信息”和“课程练习”两个模块。为了屏蔽豆豆云后台相关内容,我们封装了一个实现向后台交互的接口,涉及“加入课程”的步骤,首先开发者需要向后台申请一门课程,得到课程号; 然后对“课程信息”模块和“课程练习”模块页面的布局进行修改; 最后实现“课程”模块页面逻辑部分,从而实现“课程”模块的功能。 观看视频 5.1申请课程号 由于照搬了豆豆云的后台,涉及“加入课程”的概念,开发者需要向后台申请一个课程,得到课程号,申请链接如下: http://zjgsujiaoxue.applinzi.com/index.php/Api/User/createCourse?appid=123&courseName=1028教学&questionSet=1012&creater=大佬 其中,appid代表开发者小程序的appid; courseName代表要创建的课程的名字,开发者可自定义; questionSet代表预设的题目集(后续无法更改); creater代表创建者。 例如: 小程序appid是123,创建的课程名字是“一起来学近代史”,对应的题库是表51中的1001,即questionSet是1001,创建者是“工商大佬”,那么开发者需要访问以下链接进行课程号的申请: http://zjgsujiaoxue.applinzi.com/index.php/Api/User/createCourse?appid=123&courseName=一起来学近代史&questionSet=1001&creater=工商大佬 其中,对于questionSet的题目集,后台提供了8个题目集供开发者选择,具体详见表51。 表51题目集信息 题目集id题目集名称题 目 数 量 1001近代史题库1287 1002浙江工商大学新生入学考试题库1276 1003计算机网络题库219 1008C语言二级模拟考试题库120 1009毛概题库1766 1010C语言训练题1395 1011马克思主义基本原理概论2059 1012思修道德修养与法律基础1561 注意: 1004、1005、1006、1007的题库已作废。 选择好需要申请的课程后,访问对应的课程申请链接,网页中会即刻返回课程号,如图51所示。 图51访问链接获取课程号 此时申请课程号所用的小程序appid与该课程号已经绑定了,课程号可保存下来。所有访问该小程序的用户默认加入该课程。另外,在config.js文件中加入变量courseId,以便后面代码中的引用,如图52所示。 图52config.js中宏定义courseId 5.2“课程”模块页面布局 本节所讲的“课程”模块的页面布局是豆豆云助教的简化版本,豆豆云助教的主页面如图53所示,本案例主页面主要包括“课程信息”模块和“课程练习”模块,如图54所示。相较于豆豆云助教的主页面,本案例不涉及切换课程,没有教师端,所以不需要“在线签到”模块与“加入课程”模块。 观看视频 5.2.1“课程信息”模块页面布局 “课程信息”模块主要包括课程名称、课程创建者、加入课程的人数以及课程号,本案例课程名称为C游记,对应的是C语言题库。对于“课程信息”模块的页面布局,同样可以参考WeUI样式中表单→List→带图标、说明的列表项,如图55所示。 找到对应的WeUI样式后,将该样式的对应代码复制、粘贴到自己的项目代码中。带图标、说明的列表项具体代码如下: 图53豆豆云助教的主页面 图54案例主页面 图55带图标、说明的列表项 标题文字 说明文字 其中,image组件中src属性对应的图片资源地址改为课程对应的图片,注意将课程图片放置在images文件夹下,图片资源地址为课程图片的绝对地址。例如,本案例图片存放在images文件夹下,图片名称为course_head.png,那么图片资源路径为“/images/course_head.png”。 另外,还需要将对应wxss文件中的样式复制、粘贴到自己的代码项目中。具体代码如下: .weui-cell__hd { font-size: 0 } .weui-cell__hd image { margin-right: 16px; vertical-align: middle; width: 20px; height: 20px } 由于图片太小,因此需要调整wxss中width和height的值至80px。 “课程信息”模块主要包括课程名称、创建者、加入人数以及课程号,这些信息用标题文字的样式即可,无须使用说明文字样式。另外,通过设置字体大小与字体颜色使得课程名称更加吸引用户注意。“课程信息”模块布局如图56所示。 其中,“课程信息”模块wxml代码如下: 课程名称 创建者: 加入人数: 课程号: 在上述代码中涉及了一些新的知识点,本节对代码中涉及的知识点进行简单讲解。 1. class和style的区别 上述wxml代码中可以发现,一个view属性中既有class="weuicell__hd",又有style="position:relative;marginright:10px;"。虽然两者都可以实现对页面的修改,但是还是存在区别的。 如在myinfo页面添加一个button做测试,该button的wxml代码如下: 另外,在myinfo.wxss中添加test样式。test样式中主要是与style一样定义了字体颜色,该样式代码如下: .test{ color:red; } 该button在style中color属性值为蓝色,class调用的test样式中color属性值为红色,无论如何修改test样式中color属性的值,按钮字体颜色都是蓝色,如图57所示。在wxml中,前端读取数据都是通过就近原则,所以style是直接在页面语句中进行编写的,在程序执行时,style>class。 图56“课程信息”模块布局 图57测试button的字体颜色 2. position属性 position 属性规定元素的定位类型。这个属性定义建立元素布局所用的定位机制。任何元素都可以定位,不过绝对或固定元素会生成一个块级框,而不论该元素本身是什么类型。相对定位元素会相对于它在正常流中的默认位置偏移。position属性的值详见表52。 表52position属性的值 值描述 absolute生成绝对定位的元素,相对于static定位以外的第一个父元素进行定位。 元素的位置通过left、top、right以及bottom属性进行规定 fixed生成绝对定位的元素,相对于浏览器窗口进行定位。 元素的位置通过left、top、right以及bottom属性进行规定 relative生成相对定位的元素,相对于其正常位置进行定位。 例如,left: 20会向元素的left位置添加20像素 static默认值。没有定位,元素出现在正常的流中(忽略top、bottom、left、right或者zindex声明) sticky元素在跨越特定阈值前为相对定位,之后为固定定位 inherit规定应该从父元素继承position属性的值 3. marginright属性 marginright属性设置元素的右外边距,允许使用负值。marginright属性的值详见表53。 表53marginright属性的值 值描述 auto浏览器设置的右外边距 length定义固定的右外边距。默认值是0 %定义基于父对象总高度的百分比右外边距 inherit规定应该从父元素继承右外边距 修改“课程练习”模块image属性中marginright的值为10px和100px,页面效果如图58和图59所示。 4. display属性 display属性规定元素应该生成的框的类型。这个属性用于定义建立布局时元素生成的显示框类型。对于HTML等文档,如果使用display不谨慎会很危险,因为可能违反HTML中已经定义的显示层次结构。对于XML文档,由于XML没有内置的这种层次结构,因此display是绝对必要的。display属性的值详见表54。 图58marginright值: 10px 图59marginright值: 100px 表54display属性的值 值描述 none此元素不会被显示 block此元素将显示为块级元素,元素前后会带有换行符 inline默认值。此元素会被显示为内联元素,元素前后没有换行符 inlineblock行内块元素(CSS 2.1新增的值) listitem此元素会作为列表显示 runin此元素会根据上下文作为块级元素或内联元素显示 table此元素会作为块级表格来显示(类似),表格前后带有换行符 inlinetable此元素会作为内联表格来显示(类似
),表格前后没有换行符 tablerowgroup此元素会作为一个或多个行的分组来显示(类似) tableheadergroup此元素会作为一个或多个行的分组来显示(类似) tablefootergroup此元素会作为一个或多个行的分组来显示(类似) tablerow此元素会作为一个表格行显示(类似) tablecolumngroup此元素会作为一个或多个列的分组来显示(类似) tablecolumn此元素会作为一个单元格列显示(类似) tablecell此元素会作为一个表格单元格显示(类似
) tablecaption此元素会作为一个表格标题显示(类似
) inherit规定应该从父元素继承display属性的值 观看视频 5.2.2“课程练习”模块页面布局 “课程练习”模块主要包括顺序练习、章节练习、专项练习、收藏以及错题,相对于前面使用WeUI样式布局,“课程练习”模块要教给大家的是如何使用现有的开源代码,经过修改后开发出自己的小程序,这可以大大减轻开发者的工作量。 其中,“课程练习”模块的布局主要参考了GitHub上一个驾校考题的小程序前端代码,该项目下载地址为https://github.com/HuBinAdd/calculateswiperList。下载驾校考题源代码后,导入项目,可以看到该小程序的首页如图510所示。 找到驾校考题小程序首页对应的index页面,将驾校考题中对应的练习模块前端代码复制到自己的项目中,其中只保留专项练习与章节练习,随机练习与顺序练习就不需要了,编译后发现页面效果并不能正常显示,如图511所示。这是因为代码中涉及的样式不是WeUI样式,而是驾校考题小程序开发者自己写的样式,因此需要将index.wxss中的样式复制到自己项目的index.wxss中,但是发现“课程练习”模块还是有点问题,如图512所示。 图510驾校考题小程序的首页 图511“课程练习”模块页面异常显示 图512“课程练习”模块样式不全 导致“课程练习”模块显示与驾校考题小程序主页面不一致的原因是该部分代码中涉及的样式colhg6和colhg3在index.wxss中没有,在驾校考题小程序的源代码中,该样式写在app.wxss中,将对应的colhg6和colhg3样式复制到index.wxss文件中,具体样式代码如下: .col-hg-6 { width: 50%; } .col-hg-3 { width: 25%; } 其中涉及了float、boxsizing和width三种属性。 1. float属性 float 属性定义元素在哪个方向浮动。任何元素都可以浮动。浮动元素会生成一个块级框,而不论它本身是何种元素。如果浮动非替换元素,则要指定一个明确的宽度; 否则,它们会尽可能地窄。float属性可能的值详见表55。 表55float属性可能的值 值描述 left元素向左浮动 right元素向右浮动 none默认值。元素不浮动,并会显示在其在文本中出现的位置 inlinestart关键字,表明元素必须浮动在其所在块容器的开始一侧,在ltr脚本中是左侧,在rtl脚本中是右侧 inlineend关键字,表明元素必须浮动在其所在块容器的结束一侧,在ltr脚本中是右侧,在rtl脚本中是左侧 inherit规定应该从父元素继承float属性的值 2. boxsizing属性 boxsizing 属性允许以特定的方式定义匹配某个区域的特定元素。例如,假如需要并排放置两个带边框的框,可通过将boxsizing设置为borderbox,使页面呈现出带有指定宽度和高度的框,并把边框和内边距放入框中。boxsizing属性的值详见表56。 表56boxsizing属性的值 值描述 contentbox宽度和高度分别应用到元素的内容框。 在宽度和高度之外绘制元素的内边距和边框 borderbox为元素设定的宽度和高度决定了元素的边框盒。 也就是说,为元素指定的任何内边距和边框都将在已设定的宽度和高度内进行绘制。 通过从已设定的宽度和高度分别减去边框和内边距才能得到内容的宽度和高度 inherit规定应从父元素继承boxsizing属性的值 3. width属性 width 属性设置元素的宽度。这个属性定义元素内容区的宽度,在内容区外面可以增加内边距、边框和外边距。行内非替换元素会忽略这个属性。width属性可能的值详见表57。 表57width属性可能的值 值描述 auto默认值。浏览器可计算出实际的宽度 length使用px、cm等单位定义宽度 %定义基于包含块(父元素)宽度的百分比宽度 inherit规定应该从父元素继承width属性的值 添加colhg6和colhg3样式后,通过编译后发现专项练习与章节练习的布局只占了页面宽度的一半,使得“课程练习”模块布局不是很美观,如图513所示。这是由于专项练习和章节练习使用的是colhg3样式,该样式的width属性只有25%,两个元素总共也就50%,因此只占了页面宽度的一半。要让专项练习和章节练习撑满整个页面,就要将colhg3改为colhg6。“课程练习”模块最终页面布局如图514所示。 另外,将模拟考试元素中“模拟考试”改为“顺序练习”,“最高成绩: 分”改为“做题数: 题”。最终“课程练习”模块wxml代码如下: 图513专项练习与章节练习布局异常 图514“课程练习”模块最终页面布局 课程练习 顺序练习 做题数: 题 收藏 () 答错 () 专项练习 章节练习 5.3“课程”模块页面逻辑实现 与“课程”模块页面相关的逻辑主要包括请求加入课程与获取当前课程信息两个逻辑,由于照搬豆豆云助教的后台,因此会涉及请求加入课程的逻辑,并且需要添加获取课程信息的逻辑用于“课程信息”模块显示用户所加入课程对应的课程信息。 观看视频 5.3.1请求加入课程逻辑 在5.1节中成功申请课程号后,每个开发者都创建了一个自己的课程,本节主要内容就是如何让用户加入开发者创建的课程中。请求加入课程主要是用户 进入小程序即发生的请求,为减少请求次数, 将该逻辑写在app.js中, 通过getAddedCourse接口向后台发送请求以确认该用户是否已加入过任何课程。若 是则返回该用户所加入课程的课程号; 若 否则返回值为空,接着判断返回值是否与config.js中的 courseId相等,若不相等 ,则执行加入课程逻辑。具体代码如下: wx.request({ url: userUrl + 'getAddedCourse', data: { 'openid': wx.getStorageSync('jiaoxue_OPENID'), }, success: function(res) { if (res.data.msg!=courseId) { wx.request({ url: userUrl + 'addCourse', data: { openid: wx.getStorageSync('jiaoxue_OPENID'), courseId: courseId }, success: function(res) { if (res.data.success) { wx.setStorageSync('jiaoxue_courseList', courseId) } }, fail: function(res) { } }) } else { wx.setStorageSync('jiaoxue_addedCourse', res.data.msg) } } }) 观看视频 5.3.2获取当前课程逻辑 成功加入课程后,用户首页则需要显示所加入课程的课程信息。获取当前课程主要通过current接口向后台发送请求,获取课程信息后显示在前端,其中index.js中的代码如下: //index.js //获取应用实例 const app = getApp() const userUrl=require('../../config.js').userUrl const courseId = require('../../config.js').courseId Page({ data: { current_course:{}, }, onLoad: function () { this.getCurrentCourse(courseId) }, getCurrentCourse(course_id=''){ wx.request({ url:userUrl + 'current', data:{ current_course_id: course_id, openid: wx.getStorageSync('jiaoxue_OPENID'), }, success: res=>{ console.log('res1',res) this.setData({ current_course: res.data.data }) } }) } }) index.js文件主要在data数组中定义了一个current_course数组,然后写了一个getCurrentCourse()函数。该函数主要实现了请求名为current的API请求,向后台发送current_course_id和openid的值,请求成功后,将res.data.data赋值给current_course,使用console.log('res1',res)打印res的值,即可在Console面板中看到后台返回的课程信息,如图515所示。 图515课程信息返回值 获取课程信息后,需要将课程信息显示在首页中,因此还需要对index.wxml中“课程信息”模块的代码进行简单修改,即将“课程名称”改为变量{{current_course['name']?current_course['name']:"未知"}},并在“创建者:”“加入人数:”“课程号:”后面分别加上变量{{current_course['teacher'] ['name']?current_course['teacher']['name']:"未知"}}、{{current_course['count']?current_course['count']:"未知"}}和{{current_course['id']?current_course['id']:"未知"}}。变量通过三目运算进行判断,当获取到当前课程信息时显示对应的课程信息,如图516所示,否则显示未知,如图517所示。 图516课程信息正常显示 图517课程信息未知页面 5.4作业思考 一、 讨论题 1. 如何在代码中宏定义课程号? 2. “课程信息”模块中image组件的style样式,如果使用wxss文件要怎么实现? 二、 单选题 1. 以下()可以显示按钮为红色背景。 A. B. C. D. 2. 是图标组件,以下()可以实现一个红色、40像素大小的搜索图标。 A. B. C. D. 3. 以下关于class和style的说法正确的是()。 A. 在wxml中前端读取数据都是通过就近原则,所以style是直接在页面语句中的语句中进行编写,在程序执行时,style>class B. class对应的样式优先级大于style C. class对应的样式响应先于style D. class对应的样式和style优先级相同 4. 以下关于display: none和visibility: hidden的说法正确的是()。 A. visibility: hidden可以隐藏某个元素,但隐藏的元素仍需占用与未隐藏之前一样的空间 B. display: none可以隐藏某个元素,且隐藏的元素会占用空间。也就是说,该元素不但被隐藏了,而且该元素依然会在页面布局中存在 C. visibility: hidden 可以隐藏某个元素,且隐藏的元素不会占用任何空间 D. display: none 可以隐藏某个元素,但隐藏的元素仍需占用与未隐藏之前一样的空间 5. 以下关于display属性说法错误的是()。 A. display: inline 内联元素只需要必要的宽度,不强制换行 B. display: block 块元素是一个元素,占用了全部宽度,在前后都是换行符 C. display: none可以隐藏某个元素 D. display: hidden可以隐藏某个元素 6. 以下关于wxss常用属性的说法错误的是()。 A. backgroundcolor用于修改背景色 B. color用于修改前景色 C. border: 3px solid blue表示宽度为3像素的蓝色实线 D. border: 3px solid blue表示长度为3像素的蓝色实线 7. 以下关于wxss选择器的描述,错误的是()。 A. intro 表示选择所有拥有 class="intro"的组件 B. #firstname 表示选择拥有 id="firstname"的组件 C. view,checkbox 表示选择所有文档的 view 组件和所有的 checkbox 组件 D. view 表示选择所有 view 组件的子组件 8. 以下关于内联样式说法错误的是()。 A. 在wxml代码中,一个view组件可以同时使用两个在wxss中定义的样式 B. style又称为行内样式,可直接将样式代码写到组件的首标签中 C. 小程序使用class属性指定样式规则,其属性值是由一个或多个自定义样式类名组成,多个样式类名之间用空格分隔 D. 尽量将静态写入style中,这样可以加快渲染速度 9. 假设已有画布上下文ctx,以下()可以更改画笔的填充颜色为红色。 A. ctx.fill = 'red' B. ctx.strokeStyle = 'red' C. ctx.stoke = 'red' D. ctx.fillStyle = 'red' 10. 小程序使用wx.showToast(OBJECT)显示消息提示框,其中icon参数的值为none表示()。 A. 不显示图标 B. 显示一个对勾的图标 C. 显示一个加载动画图标 D. 显示一个打叉的图标