1. 项目背景与核心需求
高校教师教研信息管理一直是教育信息化建设中的痛点。传统的手工填报方式存在数据分散、统计困难、重复劳动等问题。我在参与某省属高校信息化改造项目时,发现教务处的王老师每周要花3个小时手工整理Excel表格,还经常出现版本混乱的情况。这种低效的管理模式促使我们开发这套教研信息填报系统。
系统需要解决三个核心问题:
- 多角色协同:教师个人填报、教研室主任审核、教务处汇总的三级管理模式
- 动态表单:不同学科(如文科、理工科)的教研成果指标差异大,需要支持自定义字段
- 数据可视化:院系领导需要实时掌握教研成果分布情况
2. 技术选型与架构设计
2.1 前后端分离架构
选择SpringBoot+Vue的组合主要基于:
- 开发效率:SpringBoot的自动配置特性可快速搭建REST API
- 性能考量:MyBatis相比Hibernate在复杂统计查询时更可控
- 前后端解耦:Vue的组件化开发适合多角色权限的前端界面
mermaid复制graph TD
A[Vue前端] -->|Axios| B(SpringBoot)
B --> C[MySQL]
B --> D[Redis缓存]
C --> E[教研数据]
D --> F[权限令牌]
2.2 数据库设计要点
教研信息表的核心字段设计:
sql复制CREATE TABLE `research_work` (
`id` bigint NOT NULL AUTO_INCREMENT,
`teacher_id` varchar(20) NOT NULL COMMENT '工号',
`work_type` tinyint NOT NULL COMMENT '1论文/2课题/3教材',
`custom_fields` json DEFAULT NULL COMMENT '动态字段',
`attachment_url` varchar(255) DEFAULT NULL,
`status` tinyint DEFAULT '0' COMMENT '0待审核/1通过/2驳回',
PRIMARY KEY (`id`),
KEY `idx_teacher` (`teacher_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
特别注意:json类型字段需要MySQL5.7+版本,如需兼容低版本可改用text字段配合JSON解析
3. 核心功能实现
3.1 动态表单引擎
通过Vue的动态组件实现字段配置化:
javascript复制// 字段配置示例
const fieldConfig = {
'paper_title': {
type: 'input',
label: '论文标题',
required: true,
maxLength: 100
},
'journal_level': {
type: 'select',
label: '期刊等级',
options: ['SCI','核心','普通']
}
}
后端采用策略模式处理不同类型字段的验证:
java复制public interface FieldValidator {
boolean validate(String value);
}
@Service
public class NumberValidator implements FieldValidator {
@Override
public boolean validate(String value) {
return StringUtils.isNumeric(value);
}
}
3.2 批量导入优化
针对历史Excel数据导入,采用Apache POI的分片读取:
java复制// 分片读取500行/次
Sheet sheet = workbook.getSheetAt(0);
for (int i = 1; i <= sheet.getLastRowNum(); i += 500) {
int end = Math.min(i + 499, sheet.getLastRowNum());
processRows(sheet, i, end); // 异步处理
}
实测对比:
| 数据量 | 传统方式 | 分片处理 |
|---|---|---|
| 5000行 | 12.3s | 3.8s |
| 20000行 | 内存溢出 | 15.2s |
4. 关键问题解决方案
4.1 并发提交冲突
使用MySQL乐观锁解决多人同时修改:
java复制@Update("UPDATE research_work SET version=version+1,... WHERE id=#{id} AND version=#{version}")
int updateWithVersion(ResearchWork work);
前端配合策略:
javascript复制async handleSubmit() {
try {
await submitForm();
} catch (e) {
if (e.response.status === 409) {
this.$message.warning('数据已被他人修改,请刷新后重试');
}
}
}
4.2 大文件上传
采用分片上传+MD5校验方案:
- 前端通过spark-md5计算文件指纹
- 按2MB分片上传
- 服务端合并时校验完整MD5
java复制// 检查分片状态
public boolean checkChunk(String md5, int chunk) {
String key = "upload:" + md5 + ":" + chunk;
return redisTemplate.opsForValue().get(key) != null;
}
5. 部署注意事项
-
内存配置:
yaml复制# application-prod.yml spring: servlet: multipart: max-file-size: 50MB max-request-size: 100MB -
定时任务配置(每日凌晨统计):
java复制@Scheduled(cron = "0 0 3 * * ?") public void generateDailyReport() { // 避免N+1查询 List<DepartmentStats> stats = mapper.selectStatsWithJoin(); stats.forEach(this::sendEmailAlert); } -
安全防护:
- 接口幂等性设计
- XSS过滤(使用Jsoup.clean)
- 定期备份策略(binlog+全量备份)
6. 源码结构说明
完整项目包含8个核心模块:
code复制src/
├── main/
│ ├── java/
│ │ └── edu/
│ │ ├── config/ # 安全配置
│ │ ├── controller/ # 三级权限控制器
│ │ ├── service/ # 业务逻辑
│ │ └── util/ # 通用工具类
│ └── resources/
│ ├── mapper/ # MyBatis映射
│ └── static/ # Vue打包文件
└── test/ # JUnit5测试
我在实际部署时发现,当教师同时在线超过200人时,需要调整Tomcat连接池配置:
properties复制# 生产环境建议
server.tomcat.max-threads=200
server.tomcat.min-spare-threads=20
spring.datasource.hikari.maximum-pool-size=100