结对编程
https://github.com/102301617/roll-call-system.git
https://www.cnblogs.com/skjs/p/19261416
https://www.bilibili.com/video/BV1d9UNBhEvH/?vd_source=e1544ea07b79d2fb2225a86c33224c43
一、结对探索(4分)(汉字序号为一级标题,下同)
1.1 队伍基本信息**(1分)(阿拉伯数字序号为二级标题,下同)
结对编号:;队伍名称:;
| 学号 | 姓名 | 作业博客链接 | 具体分工 |
|---|---|---|---|
| 102301617 | 苏坤杰 | 全部 | |
1.2 描述结对的过程(1分)
左手握右手达成共识
1.3 非摆拍的两人在讨论设计或结对编程过程的照片(2分)
👦
👕
👖
👟👟
二、原型设计(16分)
一、系统架构设计
1.1 整体架构
┌─────────────────────────────────────────────────┐
│ 前端层 (Client) │
│ React + TypeScript + Ant Design + ECharts │
│ - 用户界面展示 │
│ - 用户交互处理 │
│ - 数据可视化 │
└──────────────────┬──────────────────────────────┘│ HTTP/API│ (RESTful)
┌──────────────────▼──────────────────────────────┐
│ 后端层 (Server) │
│ Node.js + Express + TypeScript │
│ - 业务逻辑处理 │
│ - API接口提供 │
│ - 数据验证和处理 │
└──────────────────┬──────────────────────────────┘│ SQL│
┌──────────────────▼──────────────────────────────┐
│ 数据层 (Database) │
│ MySQL (db4free.net) │
│ - students 表 │
│ - roll_call_records 表 │
└─────────────────────────────────────────────────┘
1.2 技术架构分层
- 表现层:React 组件、Ant Design UI组件
- 业务逻辑层:Express 控制器、工具函数
- 数据访问层:MySQL2 连接池、数据模型
- 数据存储层:MySQL 数据库
1.3 前后端分离架构
前端 (Port 3000) 后端 (Port 3001) 数据库│ │ ││ HTTP Request │ │├────────────────────────>│ ││ │ SQL Query ││ ├─────────────────────>││ │ SQL Result ││ │<─────────────────────┤│ HTTP Response │ ││<────────────────────────┤ ││ │ │
二、数据库设计
2.1 ER图(实体关系图)
┌──────────────┐ ┌──────────────────┐
│ students │ │ roll_call_records │
├──────────────┤ ├──────────────────┤
│ id (PK) │◄────────│ id (PK) │
│ student_id │ 1:N │ student_id (FK) │
│ name │ │ call_type │
│ major │ │ is_present │
│ total_score │ │ repeat_question_ │
│ random_call_ │ │ score │
│ count │ │ answer_question_ │
│ created_at │ │ score │
│ updated_at │ │ total_score_ │
└──────────────┘ │ change ││ created_at │└──────────────────┘
关系说明:
- 一个学生可以有多个点名记录(1:N)
- 外键约束:
roll_call_records.student_id→students.student_id - 级联删除:删除学生时,自动删除相关记录
2.2 表结构详细设计
students 表
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | 主键 |
| student_id | VARCHAR(50) | UNIQUE, NOT NULL | 学号(唯一) |
| name | VARCHAR(100) | NOT NULL | 姓名 |
| major | VARCHAR(100) | NULL | 专业 |
| total_score | DECIMAL(10,2) | DEFAULT 0 | 总积分 |
| random_call_count | INT | DEFAULT 0 | 随机点名次数 |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | 更新时间 |
索引:
- PRIMARY KEY: id
- UNIQUE: student_id
- INDEX: idx_student_id (student_id)
- INDEX: idx_total_score (total_score)
roll_call_records 表
| 字段名 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | 主键 |
| student_id | VARCHAR(50) | NOT NULL, FOREIGN KEY | 学号(外键) |
| call_type | ENUM('random','sequential') | NOT NULL | 点名类型 |
| is_present | BOOLEAN | DEFAULT FALSE | 是否到达课堂 |
| repeat_question_score | DECIMAL(3,1) | DEFAULT 0 | 重复问题得分 |
| answer_question_score | DECIMAL(3,1) | DEFAULT 0 | 回答问题得分 |
| total_score_change | DECIMAL(5,2) | DEFAULT 0 | 本次积分变化 |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 |
索引:
- PRIMARY KEY: id
- FOREIGN KEY: student_id → students.student_id (ON DELETE CASCADE)
- INDEX: idx_student_id (student_id)
- INDEX: idx_created_at (created_at)
2.3 数据库设计原则
- 规范化:符合第三范式,减少数据冗余
- 性能优化:关键字段建立索引
- 数据完整性:使用外键约束和级联删除
- 可扩展性:预留扩展字段(如 major 可为空)
三、UI/UX设计
3.1 页面布局设计
3.1.1 首页(HomePage)布局
┌─────────────────────────────────────────────────────┐
│ 顶部导航栏 (AppHeader) │
│ [课堂随机点名系统] [点名系统] [积分排名] │
├─────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 学生管理 Card │ │
│ │ ┌────────────────┐ ┌────────────────┐ │ │
│ │ │ [导入Excel] │ │ [导出积分详单] │ │ │
│ │ └────────────────┘ └────────────────┘ │ │
│ │ 当前学生总数: 15 │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 点名操作 Card │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ [随机点名] │ │ [顺序点名] │ │ │
│ │ └──────────────┘ └──────────────┘ │ │
│ │ │ │
│ │ 顺序点名设置: │ │
│ │ 起始学号: [下拉选择框 ▼] │ │
│ │ 连续数量: [输入框: 1] │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 点名结果 Card (动画/结果) │ │
│ │ ┌──────────────────────────────────────┐ │ │
│ │ │ 🎲 (旋转动画) │ │ │
│ │ │ 张三 (快速切换) │ │ │
│ │ │ 随机点名中... │ │ │
│ │ └──────────────────────────────────────┘ │ │
│ │ 或 │ │
│ │ ┌──────────────────────────────────────┐ │ │
│ │ │ 张三 │ │ │
│ │ │ 学号: 2021001 │ │ │
│ │ │ 专业: 计算机科学 │ │ │
│ │ │ 当前积分: 16.94 │ │ │
│ │ └──────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────┘
3.1.2 排名页(RankingPage)布局
┌─────────────────────────────────────────────────────┐
│ 顶部导航栏 │
├─────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 积分排名 Card │ │
│ │ ┌──────────────────────────────────────┐ │ │
│ │ │ [柱形图] [折线图] [排名表格] │ │ │
│ │ │ ┌────────┐ ┌────────┐ │ │ │
│ │ │ │ 图表1 │ │ 图表2 │ │ │ │
│ │ │ └────────┘ └────────┘ │ │ │
│ │ │ ┌──────────────────────────────┐ │ │ │
│ │ │ │ 排名 | 姓名 | 学号 | 积分 │ │ │ │
│ │ │ │ 1 | 张三 | ... | 16.94 │ │ │ │
│ │ │ │ 2 | 李四 | ... | 9.80 │ │ │ │
│ │ │ └──────────────────────────────┘ │ │ │
│ │ └──────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────┘
3.2 交互流程设计
3.2.1 随机点名交互流程
┌─────────┐
│ 用户点击 │
│随机点名 │
└────┬────┘│▼
┌─────────────┐
│ 显示动画 │
│ (2秒) │
│ - 旋转骰子 │
│ - 切换名字 │
└────┬────────┘│▼
┌─────────────┐
│ 显示选中 │
│ 的学生 │
└────┬────────┘│▼
┌─────────────┐
│ 弹出记录 │
│ 弹窗 │
└────┬────────┘│▼
┌─────────────┐
│ 用户填写 │
│ 点名结果 │
└────┬────────┘│▼
┌─────────────┐
│ 保存记录 │
│ 更新积分 │
└────┬────────┘│▼
┌─────────────┐
│ 刷新显示 │
└─────────────┘
3.2.2 顺序点名交互流程
┌─────────────┐
│ 用户设置 │
│ 起始学号 │
│ 和数量 │
└────┬────────┘│▼
┌─────────────┐
│ 点击顺序 │
│ 点名按钮 │
└────┬────────┘│▼
┌─────────────┐
│ 显示学生 │
│ 列表(多个) │
└────┬────────┘│▼
┌─────────────┐
│ 用户点击 │
│ 某个学生 │
└────┬────────┘│▼
┌─────────────┐
│ 弹出记录 │
│ 弹窗 │
└────┬────────┘│▼
┌─────────────┐
│ 保存记录 │
│ 自动更新 │
│ 起始学号 │
└─────────────┘
2.1 原型工具的选择(2分)
(在此处说明选择了什么原型设计工具?为什么选择这一款原型软件?)
选择墨刀。原因:第一眼看到了
2.2 遇到的困难与解决办法**(3分)
(原型设计过程中的困难描述、解决尝试、是否解决、有何收获)
2.3 原型作品链接**(5分)
(静态原型作品得2分,交互性强的原型作品得5分)
https://modao.cc/proto/design/pb2mibojh3gd7w5sp?open_access_menu=
2.4 原型界面图片展示**(6分)
(尽可能图文并茂地在此处介绍你们队伍设计的各功能模块,创新点也在此处展示说明)

随机点名会从所有学生中随机选取一名进行点名,并设置分数

按照名单中的学生的分数进行排序
三、编程实现(14分)
**3.1 开发工具库(如文件读取包等)的使用**(1分)
后端
- Node.js + Express + TypeScript
- db4free(支持免费在线数据库)
- xlsx(Excel文件处理)
前端
- React + TypeScript
- Ant Design(UI组件库)
- ECharts(数据可视化)
- axios(HTTP请求)
**3.2 代码组织与内部实现设计(类图)**(3分)
.
├── server/ # 后端服务
│ ├── src/
│ │ ├── routes/ # 路由
│ │ ├── controllers/ # 控制器
│ │ ├── models/ # 数据模型
│ │ ├── utils/ # 工具函数
│ │ └── app.ts # 应用入口
│ ├── database/ # 数据库脚本
│ └── package.json
├── client/ # 前端应用
│ ├── src/
│ │ ├── components/ # 组件
│ │ ├── pages/ # 页面
│ │ ├── services/ # API服务
│ │ └── App.tsx # 应用入口
│ └── package.json
└── README.md
**3.3 说明算法的关键与关键实现部分流程图**(2分)
开始↓
获取所有学生列表↓
检查学生列表是否为空↓├─ 是 → 抛出错误:学生列表为空↓└─ 否↓
计算每个学生的权重weight[i] = 1 / (student[i].total_score + 1)↓
计算总权重totalWeight = Σ(weight[i])↓
生成随机数random = Math.random() * totalWeight↓
遍历学生列表,累减权重for i in students:random -= weight[i]if random <= 0:返回 students[i]↓
返回选中的学生↓
结束
3.4 贴出重要的/有价值的代码片段并解释(3分)

关键解释
- 权重计算:使用反比例函数
1/(score+1),确保积分为0时权重为1,积分越高权重越低 - 加权随机:通过累减权重的方式实现加权随机选择,时间复杂度O(n)
- 边界处理:
Math.max(0, score)确保积分非负,避免除零错误 - 精度处理:如果由于浮点数精度问题没有选中,返回最后一个学生作为兜底
价值:这是系统的核心公平性保证,确保积分低的学生有更多被点到的机会。

关键解释:
- 模块化设计:三个独立的加分项,互不干扰,易于维护和扩展
- 灵活处理:使用
null表示未记录重复问题,避免强制要求所有字段 - 规则清晰:每个规则都有明确的数值定义,符合业务需求
- 可扩展性:如果需要添加新的积分规则,只需添加新的判断分支
价值:这是积分系统的核心计算逻辑,所有积分变化都通过这个函数计算,保证了数据一致性。

关键解释:
- 事务保证:使用数据库事务确保积分更新和计数更新的原子性
- 错误处理:如果任何操作失败,自动回滚,保证数据一致性
- 资源管理:使用
finally确保连接总是被释放,避免连接泄漏 - 条件更新:根据点名类型决定是否更新随机点名次数
价值:这是数据一致性的关键保证,确保积分和统计数据的准确性。
3.5 性能分析与改进(1分)
(描述改进思路,展示性能分析图和程序中消耗最大的函数)
消耗最大的函数排名:
Excel文件解析(parseExcelFile)- 40-50%
数据库查询(getAllStudents)- 30-40%
加权随机点名(weightedRandomSelect)- 5-10%(数据量大时)
主要改进思路:
数据库:添加索引、优化查询字段
Excel解析:流式处理、禁用不必要的解析选项
算法:使用二分查找替代线性搜索
前端:虚拟滚动、防抖节流
3.6 单元测试(2分)
(展示部分单元测试代码,并说明测试的函数功能、构造测试数据的思路)

┌─────────────────────────────────────┐
│ 第3层:MySQL 应用层连接测试 │
│ - 认证测试 │
│ - 数据库存在性测试 │
│ - 查询功能测试 │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ 第2层:网络端口层测试 │
│ - TCP 端口可达性测试 │
│ - 端口连接超时检测 │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ 第1层:网络基础层测试 │
│ - 主机可达性测试(ping) │
│ - DNS 解析测试 │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ 第0层:配置信息检查 │
│ - 环境变量读取 │
│ - 配置完整性验证 │
└─────────────────────────────────────┘
测试数据库的连接,判断状态,
3.7 贴出代码commit记录(2分)

四、总结反思(11分)
**4.1 本次任务的PSP表格**(2分)
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 120 | 150 |
| Estimate | 估计这个任务需要多少时间 | 30 | 35 |
| Development | 开发 | 960 | 1080 |
| Analysis | 需求分析 (包括学习新技术) | 90 | 110 |
| Design Spec | 生成设计文档 | 120 | 150 |
| Design Review | 设计复审 | 30 | 40 |
| Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 30 | 30 |
| Design | 具体设计 | 120 | 150 |
| Coding | 具体编码 | 720 | 840 |
| Code Review | 代码复审 | 60 | 60 |
| Test | 测试(自我测试,修改代码,提交修改) | 180 | 210 |
| Reporting | 报告 | 60 | 60 |
| Test Report | 测试报告 | 30 | 30 |
| Size Measurement | 计算工作量 | 20 | 20 |
| Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 40 | 40 |
| 合计 | 1200 | 1380 |
4.2 学习进度条(每周追加)(2分)
| 第N周 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
|---|---|---|---|---|---|
| 1 | 400 | 400 | 6 | 6 | 学习React + TypeScript基础语法,掌握组件开发、Hooks使用;学习Express框架和RESTful API设计;熟悉Node.js异步编程和Promise/async-await |
| 2 | 500 | 900 | 8 | 14 | 深入学习MySQL数据库操作,掌握连接池、事务处理;学习Ant Design组件库使用;实现加权随机点名算法,理解反比例函数在权重计算中的应用 |
| 3 | 450 | 1350 | 7 | 21 | 学习Excel文件处理(xlsx库),掌握文件上传和解析;实现积分计算系统,理解模块化设计;学习前端状态管理和API调用(axios) |
| 4 | 350 | 1700 | 6 | 27 | 优化数据库查询性能,学习索引优化;实现顺序点名增强功能,掌握算法扩展;学习CSS动画和前端交互优化;解决数据库认证兼容性问题 |
| 5 | 200 | 1900 | 4 | 31 | 性能分析和优化实践;完善文档编写(算法说明、性能分析、PSP表格);总结项目经验,提出改进计划 |
| 合计 | 1900 | 1900 | 31 | 31 | - |
4.3 最初想象中的产品形态、原型设计作品、软件开发成果三者的差距如何?(3分)
最初想象中的产品像学习通的上课点名系统,不过学习通的点名系统还有学生端。
造成因素:任务中没写
(也就是谈一谈本次任务中“理想与现实的差距”,是哪些因素造成了这些差距?)
4.4 评价你的队友(1分)
需要改进的地方:AI用的还是太多了
(分别评价队友值得学习的地方和需要改进的地方)
(本部分需要包含队伍内所有成员的心得体会,若缺少一人,则队伍总分减少2分,减满4分为止)
4.5 结对编程作业心得体会(3分)
作业还是太难了,完成后有点成就感
遇到的困难:MySQL 8.0+ 认证插件不兼容错误 端口冲突; 导出积分详单失败, 前端启动脚本错误等等
启发:现在的软件开发遇到困难或不知道如何实现什么功能再也不用苦苦搜寻资料,只要问AI就能对症下药了。
(可包含但不限于评价作业难度、完成后的感受、遇到的代码模块异常或结对困难及解决方法、对之后学习或软件开发的启发)
(本部分需要包含队伍内所有成员的心得体会,若缺少一人,则队伍总分减少3分,减满6分为止)