1. 项目概述
这个学生考勤管理系统采用SSM(Spring+SpringMVC+MyBatis)作为后端框架,Vue.js作为前端框架,实现了学生日常考勤的数字化管理。我在实际开发中发现,传统纸质考勤存在数据易丢失、统计效率低等问题,而基于Web的系统能有效解决这些痛点。
系统主要包含学生信息管理、考勤记录、数据统计三大核心模块。前端采用Vue CLI搭建工程,后端使用Maven管理依赖,数据库选用MySQL 5.7。开发过程中特别注重响应式设计和数据实时性,确保教师能随时查看最新考勤状态。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型解析
2.1 后端技术栈
选择SSM框架组合主要基于以下考虑:
- Spring的IoC容器管理Bean生命周期,通过注解配置简化开发
- SpringMVC的拦截器非常适合做权限控制,比如教师和管理员的访问权限分离
- MyBatis的动态SQL能力可以灵活处理各种条件的考勤查询
数据库表设计关键点:
sql复制CREATE TABLE `attendance` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`student_id` int(11) NOT NULL COMMENT '学号',
`course_id` int(11) NOT NULL COMMENT '课程ID',
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0正常 1迟到 2早退 3缺勤',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_student` (`student_id`),
KEY `idx_course` (`student_id`,`course_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2.2 前端技术栈
Vue 2.x版本的选择考虑:
- 组件化开发便于复用考勤状态展示组件
- Vuex管理全局状态(如当前选中的课程)
- Element UI提供现成的表单和表格组件
- Axios处理与后端的API通信
典型API调用示例:
javascript复制// 获取某课程考勤记录
export function getAttendance(courseId) {
return request({
url: '/attendance/list',
method: 'get',
params: { courseId }
})
}
3. 核心功能实现
3.1 考勤打卡流程
-
教师端流程:
- 创建考勤会话(生成唯一考勤码)
- 学生扫码或输入考勤码提交位置信息
- 系统校验地理位置是否在教室范围内
- 记录考勤状态(正常/迟到/缺勤)
-
防作弊设计:
- 考勤码5分钟自动过期
- 同一IP限制重复提交
- 前后端双重时间校验
3.2 数据可视化
使用ECharts实现考勤统计:
javascript复制// 月度考勤统计图表
initChart() {
const chart = echarts.init(this.$refs.chart)
chart.setOption({
tooltip: { trigger: 'axis' },
xAxis: { data: ['1班','2班','3班'] },
yAxis: { type: 'value' },
series: [{
name: '出勤率',
type: 'bar',
data: [92, 85, 89]
}]
})
}
4. 开发实战经验
4.1 前后端联调要点
- 跨域问题解决:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST");
}
}
- 日期格式统一:
- 后端Jackson配置:
properties复制spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
- 前端axios拦截器处理:
javascript复制axios.interceptors.response.use(response => {
if (response.data instanceof Object) {
formatDates(response.data)
}
return response
})
4.2 性能优化实践
- 考勤列表分页查询SQL优化:
sql复制SELECT * FROM attendance
WHERE course_id = #{courseId}
ORDER BY create_time DESC
LIMIT #{offset}, #{pageSize}
- Vue组件懒加载:
javascript复制const AttendanceList = () => import('./views/AttendanceList.vue')
5. 典型问题解决方案
5.1 考勤状态同步问题
场景:多个教师同时修改同一学生的考勤记录
解决方案:
java复制@Transactional
public void updateAttendance(Attendance att) {
// 先查询当前版本号
Integer version = attendanceMapper.selectVersion(att.getId());
if (version != att.getVersion()) {
throw new OptimisticLockException("数据已被修改");
}
attendanceMapper.updateById(att);
}
5.2 移动端适配问题
- 使用vw单位实现响应式布局:
css复制.attendance-card {
width: 90vw;
margin: 2vw auto;
padding: 3vw;
}
- 禁止手机端缩放:
html复制<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6. 部署注意事项
- Nginx配置示例:
nginx复制server {
listen 80;
server_name attendance.example.com;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://localhost:8080;
}
}
- 数据库备份脚本:
bash复制mysqldump -uroot -p attendance > /backup/attendance_$(date +%Y%m%d).sql
实际开发中发现,使用JWT做认证时需要注意token刷新机制,我们最终采用的方案是在响应头中返回新的token,前端axios拦截器自动更新。另外Element UI的按需引入能显著减小打包体积,建议通过babel-plugin-component实现。
