【原创唯一】基于SpringBoot+Vue的课堂打卡签到考勤系统 课程设计/大作业/期末作业(源码+MySQL数据库+实验报告+PPT+远程部署)
作者介绍:专注于计算机课设、毕设辅导,本人开发,原创代码,一题一稿,绝不撞题,坚持原创,个人创作,非工作室,源码全网唯一。
✅ 原创唯一:个人原创开发,独立设计数据库与业务逻辑,拒绝工作室代码改造
✅ 技术主流:SpringBoot + Vue 前后端分离,MySQL,Echarts数据统计,可本地运行
✅ 配套资料:源码 + 数据库 + 实验报告/论文 + 答辩 PPT+部署演示+远程调试+问题解答
🍅文末获取联系🍅
摘要
随着高校信息化建设的推进,传统纸质点名方式效率低、统计难、数据难以追溯。本文设计并实现了一套基于 B/S 架构的校园课堂考勤系统,采用 Vue 3 + Element Plus 构建前端界面,Spring Boot 3 + MyBatis-Plus 构建后端服务,MySQL 存储业务数据。系统面向管理员、教师、学生三类角色:管理员负责班级、教师、学生等基础数据维护及考勤监管;教师可发布课堂签到、管理考勤明细、导出缺勤统计;学生可在签到时段内主动签到并查看个人考勤记录。系统引入「待签到—出勤—缺勤—补签」状态流转机制,超时未签到自动记为缺勤,兼顾公平性与自动化。经功能测试,系统运行稳定,满足课堂考勤管理需求。
技术栈: Spring Boot 3 + MyBatis-Plus + MySQL + Vue 3 + Element Plus + ECharts
数据库表:6张

技术范围:SpringBoot、Vue、数据可视化、小程序、HLMT、Nodejs、uni-app、MySQL数据库、ElementUi等设计与开发。
适用范围:软件工程、软件技术、数据库课程设计、计算机科学与技术、数据库系统原理、JavaWeb开发、JavaEE、Java、Web应用开发、动态网页设计的课程设计、课设、大作业、课程实验、期末作业
实验报告参考内容
实验报告可供大家参考使用


用户端功能


教师端功能




管理员端功能



数据库设计
系统数据库设计为:

admins(管理员表)
表说明:存储系统后台管理员账号,用于 Web 管理端登录与全局数据维护。
|
字段名 |
数据类型 |
约束 |
默认值 |
说明 |
|
id |
BIGINT(20) |
PRIMARY KEY, AUTO_INCREMENT |
— |
主键,自增 |
|
username |
VARCHAR(50) |
NOT NULL, UNIQUE |
— |
登录用户名,全局唯一 |
|
password |
VARCHAR(100) |
NOT NULL |
— |
BCrypt 加密后的密码哈希 |
|
real_name |
VARCHAR(50) |
NULL |
NULL |
管理员真实姓名 |
|
phone |
VARCHAR(20) |
NULL |
NULL |
联系电话 |
|
enabled |
TINYINT(4) |
NOT NULL |
1 |
账号启用状态:1=启用,0=停用 |
|
created_at |
DATETIME |
NULL |
NULL |
账号创建时间 |
索引:PRIMARY KEY(id),UNIQUE INDEX username(username)。
设计说明:管理员不开放自助注册,通常由初始化脚本预置。
teachers(教师表)
表说明:存储授课教师账号,用于教师端登录、创建签到场次及考勤管理。
|
字段名 |
数据类型 |
约束 |
默认值 |
说明 |
|
id |
BIGINT(20) |
PRIMARY KEY, AUTO_INCREMENT |
— |
主键,自增 |
|
username |
VARCHAR(50) |
NOT NULL, UNIQUE |
— |
登录用户名,全局唯一 |
|
password |
VARCHAR(100) |
NOT NULL |
— |
BCrypt 加密后的密码哈希 |
|
real_name |
VARCHAR(50) |
NULL |
NULL |
教师真实姓名 |
|
phone |
VARCHAR(20) |
NULL |
NULL |
联系电话 |
|
employee_no |
VARCHAR(30) |
NULL |
NULL |
教师工号 |
|
enabled |
TINYINT(4) |
NOT NULL |
1 |
账号启用状态:1=启用,0=停用 |
|
created_at |
DATETIME |
NULL |
NULL |
账号创建时间 |
索引:PRIMARY KEY(id),UNIQUE INDEX username(username)。
classes(班级表)
表说明:存储教学班级基础信息,作为学生归属与签到场次的目标单位。
|
字段名 |
数据类型 |
约束 |
默认值 |
说明 |
|
id |
BIGINT(20) |
PRIMARY KEY, AUTO_INCREMENT |
— |
主键,自增 |
|
class_code |
VARCHAR(30) |
NOT NULL, UNIQUE |
— |
班级编码,如 CS2024-1 |
|
name |
VARCHAR(100) |
NOT NULL |
— |
班级名称,如 计算机2024级1班 |
|
grade |
VARCHAR(30) |
NULL |
NULL |
年级,如 2024 |
|
major |
VARCHAR(100) |
NULL |
NULL |
专业名称 |
|
teacher_id |
BIGINT(20) |
NULL, FK→teachers.id |
NULL |
负责教师 ID |
|
created_at |
DATETIME |
NULL |
NULL |
创建时间 |
索引:PRIMARY KEY(id),UNIQUE INDEX class_code(class_code),INDEX teacher_id(teacher_id)。
外键:teacher_id 引用 teachers(id),ON DELETE RESTRICT,ON UPDATE RESTRICT。
删除班级前须确保无关联学生及签到场次。
students(学生表)
表说明:存储学生账号,小程序端登录主体,关联所属班级。
|
字段名 |
数据类型 |
约束 |
默认值 |
说明 |
|
id |
BIGINT(20) |
PRIMARY KEY, AUTO_INCREMENT |
— |
主键,自增 |
|
username |
VARCHAR(50) |
NOT NULL, UNIQUE |
— |
登录用户名,全局唯一 |
|
password |
VARCHAR(100) |
NOT NULL |
— |
BCrypt 加密后的密码哈希 |
|
real_name |
VARCHAR(50) |
NULL |
NULL |
学生真实姓名 |
|
phone |
VARCHAR(20) |
NULL |
NULL |
手机号码 |
|
student_no |
VARCHAR(30) |
NULL |
NULL |
学号 |
|
class_id |
BIGINT(20) |
NULL, FK→classes.id |
NULL |
所属班级 ID |
|
enabled |
TINYINT(4) |
NOT NULL |
1 |
账号启用状态:1=启用,0=停用 |
|
created_at |
DATETIME |
NULL |
NULL |
注册/创建时间 |
索引:PRIMARY KEY(id),UNIQUE INDEX username(username),INDEX class_id(class_id)。
外键:class_id 引用 classes(id),ON DELETE RESTRICT,ON UPDATE RESTRICT。
学生可通过小程序注册接口自助注册,class_id 可由管理员后续分配。
attendance_sessions(签到场次表)
表说明:存储教师发起的课堂签到任务,定义签到时间窗口与目标班级。
|
字段名 |
数据类型 |
约束 |
默认值 |
说明 |
|
id |
BIGINT(20) |
PRIMARY KEY, AUTO_INCREMENT |
— |
主键,自增 |
|
title |
VARCHAR(200) |
NOT NULL |
— |
签到标题,如 Java程序设计 第1次签到 |
|
class_id |
BIGINT(20) |
NOT NULL, FK→classes.id |
— |
目标班级 ID |
|
teacher_id |
BIGINT(20) |
NOT NULL, FK→teachers.id |
— |
发起教师 ID |
|
session_date |
DATE |
NOT NULL |
— |
签到日期 |
|
start_time |
TIME |
NULL |
NULL |
签到开始时间 |
|
end_time |
TIME |
NULL |
NULL |
签到截止时间 |
|
status |
VARCHAR(20) |
NOT NULL |
OPEN |
场次状态:OPEN=进行中,CLOSED=已结束 |
|
created_at |
DATETIME |
NULL |
NULL |
场次创建时间 |
索引:PRIMARY KEY(id),INDEX class_id(class_id),INDEX teacher_id(teacher_id)。
外键:class_id 引用 classes(id),teacher_id 引用 teachers(id),均为 RESTRICT。
教师创建场次时 status 设为 OPEN,并为班级全体学生批量生成 PENDING 考勤记录。
超过 end_time 或教师手动结束签到后,status 更新为 CLOSED,待签到学生自动记缺勤。
attendance_records(考勤明细表)
表说明:存储学生在各签到场次中的考勤状态,是签到业务的核心明细表。
|
字段名 |
数据类型 |
约束 |
默认值 |
说明 |
|
id |
BIGINT(20) |
PRIMARY KEY, AUTO_INCREMENT |
— |
主键,自增 |
|
session_id |
BIGINT(20) |
NOT NULL, FK→attendance_sessions.id |
— |
所属签到场次 ID |
|
student_id |
BIGINT(20) |
NOT NULL, FK→students.id |
— |
学生 ID |
|
status |
VARCHAR(20) |
NOT NULL |
ABSENT |
考勤状态,见第四节枚举说明 |
|
sign_time |
DATETIME |
NULL |
NULL |
签到登记时间,未签到时为 NULL |
|
remark |
VARCHAR(200) |
NULL |
NULL |
备注,补签或手动调整时填写 |
|
created_at |
DATETIME |
NULL |
NULL |
记录创建时间 |
索引:PRIMARY KEY(id),UNIQUE INDEX uk_session_student(session_id, student_id),INDEX student_id(student_id)。
外键:session_id 引用 attendance_sessions(id),student_id 引用 students(id),均为 RESTRICT。
唯一约束 uk_session_student 保证一名学生在同一场次中只有一条考勤记录。
业务创建时 status 初始值为 PENDING(待签到),而非数据库默认值 ABSENT。
系统架构

Controller及Service层核心代码写法:
@RestController
@RequiredArgsConstructor
public class AttendanceController {
private final ClazzService clazzService;
private final AttendanceService attendanceService;
// 班级分页列表接口
@GetMapping("/api/classes")
@RequireRole(UserRole.ADMIN)
public ApiResponse<PageResult<Clazz>> listClasses(
@RequestParam(required = false) String keyword,
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size) {
return ApiResponse.ok(clazzService.list(keyword, page, size));
}
// 班级下拉选项接口
@GetMapping("/api/classes/options")
@RequireRole({UserRole.ADMIN, UserRole.TEACHER})
public ApiResponse<List<Clazz>> classOptions() {
return ApiResponse.ok(clazzService.options());
}
// 新增班级接口
@PostMapping("/api/classes")
@RequireRole(UserRole.ADMIN)
public ApiResponse<Clazz> createClass(@Valid @RequestBody ClazzDTO dto) {
return ApiResponse.ok("创建成功", clazzService.create(dto));
}
// 编辑班级接口
@PutMapping("/api/classes/{id}")
@RequireRole(UserRole.ADMIN)
public ApiResponse<Clazz> updateClass(@PathVariable Long id, @Valid @RequestBody ClazzDTO dto) {
return ApiResponse.ok("更新成功", clazzService.update(id, dto));
}
// 删除班级接口
@DeleteMapping("/api/classes/{id}")
@RequireRole(UserRole.ADMIN)
public ApiResponse<Void> deleteClass(@PathVariable Long id) {
clazzService.delete(id);
return ApiResponse.ok("删除成功", null);
}
// 签到场次分页列表接口
@GetMapping("/api/attendance/sessions")
@RequireRole({UserRole.ADMIN, UserRole.TEACHER})
public ApiResponse<PageResult<AttendanceSession>> listSessions(
@RequestParam(required = false) String keyword,
@RequestParam(required = false) Long class_id,
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size) {
return ApiResponse.ok(attendanceService.listSessions(keyword, class_id, page, size));
}
// 签到场次详情接口
@GetMapping("/api/attendance/sessions/{id}")
@RequireRole({UserRole.ADMIN, UserRole.TEACHER})
public ApiResponse<AttendanceSession> getSession(@PathVariable Long id) {
return ApiResponse.ok(attendanceService.getSession(id));
}
// 创建课堂签到接口
@PostMapping("/api/attendance/sessions")
@RequireRole(UserRole.TEACHER)
public ApiResponse<AttendanceSession> createSession(@Valid @RequestBody AttendanceSessionDTO dto) {
return ApiResponse.ok("创建成功", attendanceService.createSession(dto));
}
// 结束签到接口
@PutMapping("/api/attendance/sessions/{id}/close")
@RequireRole({UserRole.ADMIN, UserRole.TEACHER})
public ApiResponse<AttendanceSession> closeSession(@PathVariable Long id) {
return ApiResponse.ok("已结束签到", attendanceService.closeSession(id));
}
// 场次考勤明细分页接口
@GetMapping("/api/attendance/records")
@RequireRole({UserRole.ADMIN, UserRole.TEACHER})
public ApiResponse<PageResult<AttendanceRecord>> listRecords(
@RequestParam Long session_id,
@RequestParam(required = false) String status,
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "100") int size) {
return ApiResponse.ok(attendanceService.listRecords(session_id, status, page, size));
}
// 更新考勤状态接口(出勤/迟到/缺勤)
@PutMapping("/api/attendance/records/{id}")
@RequireRole({UserRole.ADMIN, UserRole.TEACHER})
public ApiResponse<AttendanceRecord> updateRecord(
@PathVariable Long id, @Valid @RequestBody AttendanceRecordDTO dto) {
return ApiResponse.ok("更新成功", attendanceService.updateRecord(id, dto));
}
// 手动补签接口
@PostMapping("/api/attendance/records/{id}/makeup")
@RequireRole({UserRole.ADMIN, UserRole.TEACHER})
public ApiResponse<AttendanceRecord> makeup(
@PathVariable Long id, @RequestParam(required = false) String remark) {
return ApiResponse.ok("补签成功", attendanceService.makeup(id, remark));
}
// 学生待签到场次列表接口
@GetMapping("/api/attendance/open")
@RequireRole(UserRole.STUDENT)
public ApiResponse<List<AttendanceRecord>> openSessions() {
return ApiResponse.ok(attendanceService.listOpenForStudent());
}
// 学生主动签到接口
@PostMapping("/api/attendance/check-in")
@RequireRole(UserRole.STUDENT)
public ApiResponse<AttendanceRecord> checkIn(@RequestParam Long session_id) {
return ApiResponse.ok("签到成功", attendanceService.checkIn(session_id));
}
// 学生个人考勤明细接口
@GetMapping("/api/attendance/my")
@RequireRole(UserRole.STUDENT)
public ApiResponse<PageResult<AttendanceRecord>> myRecords(
@RequestParam(required = false) String status,
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size) {
return ApiResponse.ok(attendanceService.myRecords(status, page, size));
}
// 导出缺勤统计表接口
@GetMapping("/api/attendance/export")
@RequireRole({UserRole.ADMIN, UserRole.TEACHER})
public ResponseEntity<byte[]> export(
@RequestParam(required = false) Long class_id,
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate start_date,
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate end_date) {
byte[] data = attendanceService.exportAbsenceStats(class_id, start_date, end_date);
String filename = "absence_stats_" + LocalDate.now() + ".csv";
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + filename + "\"")
.contentType(new MediaType("text", "csv", StandardCharsets.UTF_8))
.body(data);
}
}
博主本身从事软件开发、有丰富的编程能力和水平,累积给上千名同学进行辅导,论文纯手写查重低于10%,全都顺利通过答辩!
擅长:功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文降重、长期答辩答疑辅导、腾讯会议一对一专业讲解辅导答辩、模拟答辩演练、和理解代码逻辑思路等。
更多个人原创作品👇🏻
获取联系
项目功能完整,可在本地运行,并可远程调试,确保运行顺利!
查看👇🏻👇🏻获取联系方式👇🏻👇🏻
更多推荐

所有评论(0)