2025软工K班结对编程任务
https://github.com/Roseeeeeeeeeeeeeeeeee/take-attendance-miniapp.git
https://www.cnblogs.com/Cindy051010/p/19261406
https://www.bilibili.com/video/BV1d9UNBhEP4/?share_source=copy_web&vd_source=9eaea57457ed9365879ef1dfa175f7e9
一、结对探索(4分)
1.1 队伍基本信息(1分)
结对编号:20;队伍名称:对对队;
| 学号 | 姓名 | 作业博客链接 | 具体分工 |
|---|---|---|---|
| 102301603 | 龙玉凤 | https://www.cnblogs.com/Cindy051010/p/19261406 | 原型设计、UI设计 |
| 052301239 | 王志宸 | https://www.learnerhub.net/resources/5162 | 算法设计、编程实现 |
1.2 描述结对的过程(1分)
我们认识很久了比较熟,而且各自都有擅长的部分,就一起组队了。
1.3 非摆拍的两人在讨论设计或结对编程过程的照片(2分)

二、原型设计(16分)
2.1 原型工具的选择(2分)
本次原型设计选择了墨刀作为主要工具,选择墨刀的原因如下:
- 操作便捷性:墨刀的拖拽式交互设计降低了学习成本,无需复杂代码基础即可快速搭建界面。
- 移动端适配友好:智慧点名系统面向移动端场景,墨刀提供了丰富的手机尺寸模板和移动端组件,能够高效还原设计需求。
- 交互逻辑可视化:支持页面跳转、状态切换等交互设置,可直观呈现点名流程(随机点名→评分→排名展示)的连贯性,便于测试用户体验。
2.2 遇到的困难与解决办法(3分)
困难 1:复杂交互逻辑的实现
描述:设计 "随机点名 - 评分 - 积分排名联动" 流程时,难以通过基础组件实现实时数据更新。
解决尝试:查阅墨刀官方教程,利用 "变量" 和 "条件判断" 功能模拟数据联动,将复杂流程拆分为 "点名→评分提交→排名页刷新" 三个独立页面,通过跳转逻辑衔接。
结果:解决。虽然无法实现真实数据运算,但通过页面状态模拟达到了流程演示的效果。
收获:学会了拆解复杂交互,利用工具现有功能找到替代方案,平衡原型保真度与开发效率。
困难 2:组件样式不统一、整体布局颜色不统一
描述:不同页面的按钮、卡片样式存在差异,包括颜色、圆角大小等,影响了视觉一致性。
解决尝试:使用墨刀的 "组件库" 功能,将常用元素比如绿色渐变按钮、圆角卡片保存为复用组件,统一修改样式。
结果:解决。通过组件复用确保了微信小程序整体设计风格统一。
收获:认识到了组件化设计的重要性,提前规划设计规范可以减少后期调整成本。
2.3 原型作品链接(5分)
【智慧课堂点名系统-原型作品】 https://www.bilibili.com/video/BV1NvUNByEVt/?share_source=copy_web&vd_source=9eaea57457ed9365879ef1dfa175f7e9
2.4 原型界面图片展示(6分)
1. 首页页面
首页是系统的核心操作界面,包含三大核心功能区域:
-
课堂点名区:支持两种点名模式以满足不同课堂场景需求
(1)随机点名:通过按钮触发以随机算法抽取学生,增加课堂互动的随机性
(2)按学号顺序点名:适合系统性点名检查 -
点名结果展示区:实时显示当前点名结果,包括学生姓名、学号、专业、当前积分和被点名次数
-
回答问题评分区:教师可对学生回答进行量化评分
(1)通过滑块或快捷按钮设置 "回答准确度评分"(0.5~3.0 分)
(2)支持 "能否准确重复问题" 的开关(能够重复问题 + 0.5 分,否则 - 1 分)
(3)系统自动计算总得分并展示评分明细,确认后提交积分

2. 排名页面
- 积分可视化图表:使用柱状图展示排名前五的学生积分与随机点名次数
- 详细排名列表:按积分高低展示学生积分排名,包含排名序号、姓名、学号、专业、随机点名次数及总积分,且对前三名采用特殊样式标注(金色、银色、红色背景),增强视觉区分度以直观呈现学生表现差异。

3. 我的页面
- 支持学生名单的导入(如 Excel 文件)和积分详单的导出(Excel格式),方便教师批量管理数据;
- 积分详单记录每个学生的学号、姓名、专业、随机点名次数、总积分,作为课堂参与度的参考指标。

4. 创新点说明
- 构建了多维度的积分管理体系,将点名结果(到达 + 1 分、缺勤 - 1 分)与回答问题评分(涵盖能否重复问题的能力、回答准确度等维度)相结合,且分值动态可调(可以滑动滑动条给出单位分为0.1的分数,也可以选择固定的选项值)形成了完整的学生课堂表现量化模型。

- 积分不仅作为点名权重依据,还通过排名可视化功能以直观柱状图和列表呈现,柱状图直接显示排名前5名同学的积分,点击相应柱状图还会呈现被随机点名的次数,可以让老师实时掌握课堂参与情况,激发学生积极性。

三、编程实现(14分)
3.1 开发工具库(如文件读取包等)的使用(1分)
-
通过
wx.chooseMessageFile从客户端会话选择文件,进而使用wx.getFileSystemManager的readFile解析 excel 文件为 json 数据 -
通过
ec-canvas在微信小程序中使用 echarts 来可视化点名的排名信息
3.2 代码组织与内部实现设计(类图)(3分)
1. IndexPage (pages/index/index.js)
职责:主点名页面,负责数据拉取/缓存、随机抽人算法、到课/缺席/答题分数逻辑、本地/云端更新。
关键方法:fetchData(), useLocalCache(), selStuRandom(), selStuBySid(), handleSel(), updatePoints(), changeAttstate()
2. RankPage (pages/rank/rank.js)
职责:从云端读取按 point 排序的前 10 条,渲染排名与 echarts 柱状图。
关键方法:fetchData(), initBarChart()
3. MinePage (pages/mine/mine.js)
职责:导入 Excel(解析为学生列表并入库)、导出 Excel、清理旧名单、本地缓存管理。
关键方法:getListByExcel(), readExcel(), saveToDB(), getAllStudentsData(), saveAndOpenExcel(), clearStuData()
4. 类图

3.3 说明算法的关键与关键实现部分流程图(2分)
1. 算法的关键
此算法的核心设计目标是实现 "反向激励":即当前积分越低的学生,被点到的概率越高;积分越高的学生,被点到的概率越低,但不会完全不被点到。
代码中计算权重的核心逻辑位于 selStuRandom 函数中,公式为:
weight = max(1/(Score + Offset)^k, minWeight)
通过反比例函数来控制学生权重的下降速度,积分越高,权重下降越快,并使用 offset 偏移量来保证代码的正确性,起到了防止反比例函数的分母为0的作用,此外还通过设置最小权重值来保证积分很高的学生也有被点中的概率,并且这个概率都是可以灵活调整的。
在计算出权重后,使用 "轮盘赌" 的方式来选择点中学生,具体实现如下:
- 总长度:将所有学生的权重加起来得到 sum。
- 随机点:在 0 到 sum 之间生成一个随机数 ran。
- 命中检测:遍历学生列表,用 ran 依次减去每个学生的权重。当 ran 减为负数时,当前遍历到的学生即为被点名的学生。
2. 流程图

3.4 贴出重要的/有价值的代码片段并解释(3分)
1. 数据同步逻辑
// pages/index/index.js 中的数据同步逻辑
fetchData() {
db.collection('students-attendance').count().then(async res => {
const total = res.total
const fetchCnt = Math.ceil(total / 20)
const tasks = []
for (let i = 0; i < fetchCnt; i++) {
const promise = db.collection('students-attendance')
.skip(i * 20).limit(20).get()
tasks.push(promise)
}
const results = await Promise.all(tasks)
})
}
该函数实现了分页批量数据同步和离线缓存机制。使用 Promise.all 并发请求提高效率,同时支持离线使用,体现了良好的用户体验设计。
2. 积分更新逻辑
// pages/index/index.js 中的积分更新逻辑
updatePoints(point) {
// UI更新
this.setData({ stuAtt: list, selStuData: stu })
// 本地存储更新
wx.setStorage({ key: 'stuAtt', data: list })
// 云数据库更新
db.collection('students-attendance').doc(docId).update({
data: { point: relPoint }
})
}
此函数价值在于实现了三层数据同步机制(UI → 本地存储 → 云数据库),确保数据一致性,即使网络异常也能保证本地数据正确。
3.5 性能分析与改进(1分)
程序中消耗最大的函数就是主页中的 updatePoints,改进思路是通过引入 Map 索引机制,将学生数据查找从 O(n) 的线性遍历优化为 O(1) 的直接定位,从而大幅提升点名小程序在更新积分和统计点名次数等频繁操作时的性能表现。
1. 改进前性能


2. 改进后


3. 性能对比测试

3.6 单元测试(2分)
global.testAttendanceFunctions = function() {
console.log('点名测试');
try {
const pages = getCurrentPages();
if (pages.length === 0) {
return;
}
const currentPage = pages[pages.length - 1];
if (currentPage.route === 'pages/index/index') {
// 测试索引创建功能
console.group('测试索引创建功能');
testIndexCreation(currentPage);
// 测试积分更新功能
console.group('积分更新功能');
testPointUpdate(currentPage);
// 测试4: 随机算法测试
console.group('测试4 - 随机算法测试');
testRandomAlgorithm(currentPage);
console.groupEnd();
console.log('所有测试完成');
} else {
console.warn('当前页面不是首页,请在首页运行测试');
console.log('当前页面:', currentPage.route);
}
} catch (error) {
console.error('测试中出错:', error);
}
}
随机算法测试代码
function testRandomAlgorithm(pageInstance) {
console.log('开始随机算法测试...');
const testData = [
{ sid: 'LOW001', name: '低分学生', point: 1 },
{ sid: 'MID001', name: '中分学生', point: 10 },
{ sid: 'HIGH001', name: '高分学生', point: 30 }
];
const mockPage = {
data: { stuAtt: testData },
setData: function(data) {
Object.assign(this.data, data);
if (data.selStuData) {
console.log('选中学生:', data.selStuData.name, '积分:', data.selStuData.point);
}
}
};
}
构造思路
- 真实性优先:优先使用页面实际数据,确保测试环境真实
- 兜底机制:无数据时自动生成基础测试数据
- 数据多样性:包含不同积分值的学生,覆盖多种场景
3.7 贴出代码commit记录(2分)

四、总结反思(11分)
4.1 本次任务的PSP表格(2分)
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 30 | 45 |
| Estimate | 估计这个任务需要多少时间 | 4500 | 5000 |
| Development | 开发 | 2400 | 1800 |
| Analysis | 需求分析 (包括学习新技术) | 180 | 120 |
| Design Spec | 生成设计文档 | 30 | 30 |
| Design Review | 设计复审 | 35 | 25 |
| Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 30 | 20 |
| Design | 具体设计 | 360 | 300 |
| Coding | 具体编码 | 1500 | 1200 |
| Code Review | 代码复审 | 60 | 50 |
| Test | 测试(自我测试,修改代码,提交修改) | 50 | 50 |
| Reporting | 报告 | 60 | 90 |
| Test Report | 测试报告 | 20 | 30 |
| Size Measurement | 计算工作量 | 25 | 20 |
| Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | 30 | 30 |
| 合计 | 4810 | 3810 |
4.2 学习进度条(每周追加)(2分)
| 第 N 周 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
|---|---|---|---|---|---|
| 1 | 987 | 987 | 9 | 9 | 熟悉了wxml、wxss |
| 2 | 986 | 1973 | 10 | 19 | 学习了excel的二进制解析法,微信小程序的各种API |
4.3 最初想象中的产品形态、原型设计作品、软件开发成果三者的差距如何?(3分)
最终的产品形态和预想的差距不大,最初想象的产品是一个智能化的课堂点名和提问小程序,包含随机点名、按学号顺序点名、Excel 表格导入导出、积分录入与排名展示、学生缺勤趋势预测等核心功能。但受限于时间成本和技术复杂度,通过逐步完善和调整,最终的开发成果基本复原了全部的原型设计方案,支持随机点名和按学号顺序点名两种点名模式以满足不同课堂场景需求,并且实现了基于回答问题表现的积分计算功能和积分排名的可视化以及学生名单的导入和积分详单的导出,方便教师批量管理数据。
4.4 评价你的队友(1分)
龙玉凤
王志宸同学非常优秀!本次作业他主要负责算法设计和编程实现,他的编程能力很强而且效率很高,有耐心还有很强的执行力,能够精准抓住需求提炼关键逻辑,在原型设计过程中他也提出了很多建设性建议,我们一起讨论改进,沟通很顺畅,非常顺利愉快的一次合作。
但沟通时回复较慢,稍微影响了协作效率,可以多看看信息,对协作工作流较生疏,可以多组队多联系来提高协作能力。
王志宸
龙玉凤同学工作效率高,内容完成度高,UI设计简洁优美,沟通亲和,表达简明扼要,主动分担任务,自主性强。
但原型设计的按钮点击只有缩放效果,可以增加状态色变化,比如点击时饱和度降低10%以增加用户体验感。积分排名可视化区域与下方排名列表的视觉衔接较弱,可以适当增加分割线或背景色过渡。
4.5 结对编程作业心得体会(3分)
龙玉凤
本次结对编程作业中,我主要责原型设计与 UI 设计部分,从线框图勾勒到视觉落地的整个过程让我对 "设计如何服务功能"、"协作如何平衡创意与落地" 有了更加具体的认识。遇到的挑战是对多页面一致性的把控,底部标签栏的图标风格、按钮的圆角弧度、提示文字的字号都会影响整体的体验,初版原型设计的标题背景颜色和积分排名可视化柱状图颜色与"首页" 和 "排名" 页的按钮风格不一致,经队友提醒后统一为浅色系风格,提高了视觉丰富度,整体界面美观清晰。结对编程的模式让我深刻体会到了团队协作的价值与力量,从需求分析到功能实现,再到细节打磨,两人协作的模式不仅提升了产品质量,更让我对协同工作有了新的理解。
王志宸
本次结对编程作业难度适中,对我的软件开发能力以有很大提升,同时也让我学习到了一些业务规范,受益匪浅。在完成了整个项目的开发后,我有一种平静感。在实际的开发过程中我也遇到了很多困难,如导入学生信息表后按学号顺序点名的顺序错乱问题,解决方法就是耐心研究已写代码一步步进行调试,最终找到问题所在是上传数据库时数据项并非一定严格按照json的数据顺序,而是到达先后会受网络波动影响。找到了问题的根本之后就好解决了,添加一个名单排序就能实现正确顺序点名。在遇到问题与解决问题的过程中,我明白了在今后的软件开发过程中一定要耐心,静心,找出问题关键之后逐一击破。总之,此次结对编程不仅提高了我的学习能力与编程能力,还提高了我的团队协作能力,明白了同伴的重要性,只有团结协作才能共渡难关。

浙公网安备 33010602011771号