基于浏览器-服务器架构的高校教学任务统计系统
系统界面展示

技术架构
SpringBoot - 后端技术栈
SpringBoot作为现代Java开发的核心框架,提供了快速构建企业级应用的解决方案。其关键优势包括:
- 简化配置:通过自动配置机制,大幅减少XML和注解配置量
- 内嵌容器:集成Tomcat、Jetty等服务器,实现独立部署
- 微服务支持:与Spring Cloud无缝集成,便于构建分布式系统
- 数据访问:提供JPA、MyBatis等多种数据访问方式
- 安全控制:集成Spring Security,实现灵活的身份认证和授权
Vue.js - 前端实现方案
Vue.js作为渐进式JavaScript框架,在构建交互式Web应用方面表现出色。主要特性包括:
- 响应式数据绑定:基于MVVM模式,实现数据与视图的自动同步
- 组件化开发:支持组件封装,提高代码复用性和可维护性
- 路由管理:通过Vue Router实现单页面应用的路由控制
- 状态管理:Vuex提供集中式状态管理方案
- 生态系统:与Element UI、Vant等UI组件库完美配合
前后端分离开发模式
接口规范设计:后端采用RESTful风格设计API,统一数据交换格式和状态码。 前端界面实现:Vue.js负责用户界面渲染和交互逻辑,通过Axios库与后端通信。 数据交互流程:前后端通过JSON格式进行数据交换,确保接口契约一致性。 部署策略:前端资源通过Nginx等静态服务器分发,后端应用部署在应用服务器上。
系统可行性分析
在项目启动阶段,可行性评估是确保项目成功的关键环节。本系统旨在解决传统人工统计教学工作中存在的效率低下、数据不准确等问题。
技术可行性评估
采用Java生态系统作为开发基础,SpringBoot框架提供了成熟稳定的解决方案。Vue.js前端框架确保了良好的用户体验和开发效率。MySQL数据库系统满足数据持久化需求。整体技术栈选择合理,技术风险可控。
经济可行性考量
系统实施后可显著减少人工统计工作量,降低管理成本。自动化数据处理提高工作效率,间接创造经济价值。投入产出比分析表明,系统开发成本可在1-2年内通过效率提升收回。
操作实用性分析
系统界面设计简洁直观,降低用户学习成本。工作流程符合教学管理实际需求,易于被教师和管理人员接受。权限分级设计确保数据安全和操作合规性。
系统测试方案
系统测试是保障软件质量的重要环节,通过全面验证确保系统满足设计要求和用户期望。
测试目标与范围
系统测试旨在验证整个应用的功能完整性、性能表现和用户体验。测试范围包括所有功能模块、数据交互流程、用户界面响应以及异常处理机制。
功能测试用例
登录模块测试
| 测试场景 | 输入数据 | 预期结果 | 实际结果 | 测试结论 |
|---|---|---|---|---|
| 正常登录 | 有效用户名和密码 | 系统登录成功 | 登录成功 | 通过 |
| 密码错误 | 有效用户名和错误密码 | 提示密码错误 | 显示错误提示 | 通过 |
| 验证码错误 | 正确凭据和错误验证码 | 提示验证码错误 | 显示验证码错误 | 通过 |
| 用户名为空 | 空用户名和有效密码 | 提示用户名必填 | 显示必填提示 | 通过 |
| 密码为空 | 有效用户名和空密码 | 提示密码必填 | 显示必填提示 | 通过 |
用户管理测试
| 测试场景 | 输入数据 | 预期结果 | 实际结果 | 测试结论 |
|---|---|---|---|---|
| 新增用户 | 完整用户信息 | 用户创建成功 | 列表显示新用户 | 通过 |
| 修改用户 | 更新用户信息 | 信息更新成功 | 显示修改后数据 | 通过 |
| 删除用户 | 选择用户删除 | 确认后删除成功 | 列表不再显示 | 通过 |
| 用户名重复 | 已存在用户名 | 提示用户名重复 | 显示重复提示 | 通过 |
| 必填项缺失 | 空必填字段 | 提示必填信息 | 显示相应提示 | 通过 |
数据库设计
用户信息表(user_info)
- 表说明: 存储系统用户的基本信息
- 字段定义:
| 字段名 | 数据类型 | 主键 | 非空 | 说明 |
|---|---|---|---|---|
| user_id | BIGINT | 是 | 是 | 用户唯一标识 |
| login_name | VARCHAR(50) | 否 | 是 | 登录账号 |
| password_hash | VARCHAR(255) | 否 | 是 | 加密密码 |
| real_name | VARCHAR(50) | 否 | 是 | 真实姓名 |
| gender | CHAR(1) | 否 | 是 | 性别(M/F) |
| VARCHAR(100) | 否 | 是 | 电子邮箱 | |
| mobile | VARCHAR(20) | 否 | 否 | 联系电话 |
| status | TINYINT | 否 | 是 | 账号状态(0-禁用,1-启用) |
| create_time | DATETIME | 否 | 是 | 创建时间 |
| update_time | DATETIME | 否 | 是 | 更新时间 |
角色权限表(role_info)
- 表说明: 存储系统角色和权限信息
- 字段定义:
| 字段名 | 数据类型 | 主键 | 非空 | 说明 |
|---|---|---|---|---|
| role_id | BIGINT | 是 | 是 | 角色ID |
| role_code | VARCHAR(50) | 否 | 是 | 角色编码 |
| role_name | VARCHAR(50) | 否 | 是 | 角色名称 |
| role_desc | VARCHAR(255) | 否 | 否 | 角色描述 |
| create_time | DATETIME | 否 | 是 | 创建时间 |
| update_time | DATETIME | 否 | 是 | 更新时间 |
教学任务表(teaching_task)
- 表说明: 记录教师教学任务信息
- 字段定义:
| 字段名 | 数据类型 | 主键 | 非空 | 说明 |
|---|---|---|---|---|
| task_id | BIGINT | 是 | 是 | 任务ID |
| teacher_id | BIGINT | 否 | 是 | 教师ID |
| course_name | VARCHAR(100) | 否 | 是 | 课程名称 |
| course_type | VARCHAR(50) | 否 | 是 | 课程类型 |
| class_hours | INT | 否 | 是 | 课时数 |
| semester | VARCHAR(20) | 否 | 是 | 学期 |
| academic_year | VARCHAR(10) | 否 | 是 | 学年 |
| task_status | TINYINT | 否 | 是 | 任务状态 |
| create_time | DATETIME | 否 | 是 | 创建时间 |
| update_time | DATETIME | 否 | 是 | 更新时间 |
工作量统计表(workload_stats)
- 表说明: 存储教师工作量统计结果
- 字段定义:
| 字段名 | 数据类型 | 主键 | 非空 | 说明 |
|---|---|---|---|---|
| stats_id | BIGINT | 是 | 是 | 统计ID |
| teacher_id | BIGINT | 否 | 是 | 教师ID |
| total_hours | DECIMAL(10,2) | 否 | 是 | 总课时数 |
| teaching_hours | DECIMAL(10,2) | 否 | 是 | 教学课时 |
| research_hours | DECIMAL(10,2) | 否 | 是 | 科研课时 |
| guidance_hours | DECIMAL(10,2) | 否 | 是 | 指导课时 |
| semester | VARCHAR(20) | 否 | 是 | 统计学期 |
| academic_year | VARCHAR(10) | 否 | 是 | 统计学年 |
| stats_date | DATE | 否 | 是 | 统计日期 |
| create_time | DATETIME | 否 | 是 | 创建时间 |
核心代码实现
@GetMapping("/teaching-tasks/page")
public Result<PageResult<TeachingTask>> getTaskPage() {
TeachingTaskQuery query = getObject(TeachingTaskQuery.class);
LambdaQueryWrapper<TeachingTask> wrapper = new LambdaQueryWrapper<>();
// 条件过滤
if (StringUtils.isNotBlank(query.getCourseName())) {
wrapper.like(TeachingTask::getCourseName, query.getCourseName());
}
if (StringUtils.isNotBlank(query.getTeacherName())) {
wrapper.like(TeachingTask::getTeacherName, query.getTeacherName());
}
if (query.getSemester() != null) {
wrapper.eq(TeachingTask::getSemester, query.getSemester());
}
if (query.getAcademicYear() != null) {
wrapper.eq(TeachingTask::getAcademicYear, query.getAcademicYear());
}
// 时间范围查询
Date[] dateRange = query.getDateRange();
if (dateRange != null && dateRange[0] != null) {
wrapper.ge(TeachingTask::getCreateTime, dateRange[0]);
}
if (dateRange != null && dateRange[1] != null) {
wrapper.le(TeachingTask::getCreateTime, dateRange[1]);
}
// 排序
wrapper.orderByDesc(TeachingTask::getCreateTime);
// 分页查询
return Result.success(teachingTaskService.page(getCurrentPage(), wrapper));
}
数据库初始化脚本
-- 用户信息表
CREATE TABLE `user_info` (
`user_id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`login_name` varchar(50) NOT NULL COMMENT '登录账号',
`password_hash` varchar(255) NOT NULL COMMENT '密码哈希',
`real_name` varchar(50) NOT NULL COMMENT '真实姓名',
`gender` char(1) NOT NULL COMMENT '性别',
`email` varchar(100) NOT NULL COMMENT '邮箱',
`mobile` varchar(20) DEFAULT NULL COMMENT '手机号',
`status` tinyint NOT NULL DEFAULT '1' COMMENT '状态:0-禁用,1-启用',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '更新时间',
PRIMARY KEY (`user_id`),
UNIQUE KEY `uk_login_name` (`login_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';
-- 角色表
CREATE TABLE `role_info` (
`role_id` bigint NOT NULL AUTO_INCREMENT COMMENT '角色ID',
`role_code` varchar(50) NOT NULL COMMENT '角色编码',
`role_name` varchar(50) NOT NULL COMMENT '角色名称',
`role_desc` varchar(255) DEFAULT NULL COMMENT '角色描述',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '更新时间',
PRIMARY KEY (`role_id`),
UNIQUE KEY `uk_role_code` (`role_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
-- 教学任务表
CREATE TABLE `teaching_task` (
`task_id` bigint NOT NULL AUTO_INCREMENT COMMENT '任务ID',
`teacher_id` bigint NOT NULL COMMENT '教师ID',
`course_name` varchar(100) NOT NULL COMMENT '课程名称',
`course_type` varchar(50) NOT NULL COMMENT '课程类型',
`class_hours` int NOT NULL COMMENT '课时数',
`semester` varchar(20) NOT NULL COMMENT '学期',
`academic_year` varchar(10) NOT NULL COMMENT '学年',
`task_status` tinyint NOT NULL DEFAULT '1' COMMENT '任务状态',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '更新时间',
PRIMARY KEY (`task_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='教学任务表';
-- 工作量统计表
CREATE TABLE `workload_stats` (
`stats_id` bigint NOT NULL AUTO_INCREMENT COMMENT '统计ID',
`teacher_id` bigint NOT NULL COMMENT '教师ID',
`total_hours` decimal(10,2) NOT NULL COMMENT '总课时',
`teaching_hours` decimal(10,2) DEFAULT NULL COMMENT '教学课时',
`research_hours` decimal(10,2) DEFAULT NULL COMMENT '科研课时',
`guidance_hours` decimal(10,2) DEFAULT NULL COMMENT '指导课时',
`semester` varchar(20) NOT NULL COMMENT '学期',
`academic_year` varchar(10) NOT NULL COMMENT '学年',
`stats_date` date NOT NULL COMMENT '统计日期',
`create_time` datetime NOT NULL COMMENT '创建时间',
PRIMARY KEY (`stats_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='工作量统计表';