1. 项目背景与核心价值
大学生创新创业竞赛近年来已成为高校培养学生实践能力的重要平台。随着参赛团队数量激增,传统纸质申报和线下路演管理模式暴露出效率低下、信息不对称、评审流程不透明等问题。我们团队开发的这套系统正是为了解决这些痛点,为竞赛组织方和参赛学生提供全流程数字化管理支持。
系统采用前后端分离架构,后端基于SpringBoot+MyBatis技术栈,前端使用Vue3框架,数据库选用MySQL。这种技术组合既保证了系统稳定性,又能快速响应前端交互需求。在实际部署中,系统成功支撑了某省2023年大学生双创竞赛的全程管理,服务了超过300支参赛团队和50余位评审专家。
2. 系统架构设计解析
2.1 技术选型考量
后端选择SpringBoot主要基于以下考虑:
- 自动配置特性大幅减少XML配置
- 内嵌Tomcat简化部署流程
- 丰富的Starter依赖可快速集成MyBatis、Redis等组件
- 完善的监控端点便于生产环境运维
前端采用Vue3的核心优势:
- Composition API使代码组织更灵活
- 更好的TypeScript支持
- 更小的打包体积和更高的运行效率
- 与Element Plus组件库完美配合
数据库选型对比了MySQL和PostgreSQL:
- MySQL在高校信息化环境中更普及
- 事务隔离级别完全满足竞赛业务需求
- 社区支持完善,运维成本低
2.2 系统模块划分
code复制竞赛申报模块
├── 团队注册
├── 项目申报
├── 材料上传
└── 进度跟踪
评审管理模块
├── 专家分配
├── 在线评分
├── 成绩统计
└── 结果公示
路演管理模块
├── 场次安排
├── 直播接入
├── 互动问答
└── 录像回放
系统管理模块
├── 用户权限
├── 日志审计
├── 数据备份
└── 消息通知
3. 核心功能实现细节
3.1 申报材料多级审核流程
采用状态机模式设计审核流程:
java复制public enum AuditStatus {
DRAFT, // 草稿
TEAM_LEADER_SUBMITTED, // 队长提交
SCHOOL_ADMIN_CHECKED, // 校级审核
PROVINCE_ADMIN_APPROVED // 省级通过
}
关键实现要点:
- 使用MyBatis的TypeHandler处理枚举存储
- 审核日志采用AOP方式记录
- 状态变更触发站内信通知
- 支持PDF格式申报书在线预览
3.2 评审专家双盲分配算法
为保证公平性,系统实现了双盲评审机制:
- 项目领域标签化(使用IK分词器)
- 专家研究方向向量化
- 基于余弦相似度匹配
- 人工可调整分配结果
核心代码片段:
java复制public List<Expert> matchExperts(Project project) {
List<Expert> candidates = expertMapper.selectByTags(project.getTags());
return candidates.stream()
.sorted(Comparator.comparingDouble(e ->
cosineSimilarity(project.getVector(), e.getVector())))
.limit(3)
.collect(Collectors.toList());
}
3.3 路演直播低延迟方案
针对线上路演的特殊需求,我们实现了:
- WebRTC直连与SFU转发混合模式
- 信令服务器使用SpringBoot+WebSocket
- 前端采用vue-webrtc组件
- 支持屏幕共享与PPT同步演示
关键配置参数:
yaml复制webrtc:
ice-servers:
- urls: stun:stun.l.google.com:19302
bandwidth:
video: 1500kbps
audio: 64kbps
resolution: 1280x720
4. 数据库设计与优化
4.1 主要表结构设计
sql复制CREATE TABLE `project` (
`id` bigint NOT NULL AUTO_INCREMENT,
`team_id` bigint NOT NULL,
`title` varchar(100) NOT NULL,
`category` enum('创新','创业') NOT NULL,
`status` enum('draft','submitted','approved','rejected') NOT NULL,
`abstract` text,
`attachment_url` varchar(255),
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_team_status` (`team_id`,`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
4.2 性能优化实践
-
热点数据缓存策略:
- 使用Redis缓存项目列表
- 本地缓存(Caffeine)存储配置信息
- 缓存失效采用主动更新+定时刷新
-
查询优化案例:
java复制// 优化前:N+1查询问题
List<Project> projects = projectMapper.selectAll();
projects.forEach(p -> {
p.setTeam(teamMapper.selectById(p.getTeamId()));
});
// 优化后:单次JOIN查询
@Select("SELECT p.*, t.name as team_name " +
"FROM project p LEFT JOIN team t ON p.team_id = t.id")
List<ProjectVO> selectAllWithTeam();
5. 安全防护措施
5.1 权限控制实现
采用RBAC模型结合业务特性:
- 角色分为:超级管理员、省级管理员、校级管理员、指导教师、学生
- 权限粒度控制到按钮级别
- 数据权限实现学校隔离
Spring Security配置示例:
java复制http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/school/**").access("@schoolSecurity.check(authentication,request)")
.anyRequest().authenticated();
5.2 敏感数据保护
- 密码存储:BCrypt加密
- 日志脱敏:自定义Logback转换器
- 接口防刷:Guava RateLimiter
- XSS防护:自定义HttpServletRequestWrapper
6. 部署与运维方案
6.1 容器化部署
Docker Compose编排文件示例:
yaml复制version: '3'
services:
backend:
image: registry.cn-hangzhou.aliyuncs.com/edu/contest-backend:1.0
ports:
- "8080:8080"
depends_on:
- redis
- mysql
frontend:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./dist:/usr/share/nginx/html
6.2 监控告警配置
- Spring Boot Actuator暴露健康指标
- Prometheus采集JVM监控数据
- Grafana展示关键指标看板
- 关键业务指标:
- 申报提交QPS
- 评审平均响应时间
- 直播并发连接数
7. 典型问题排查实录
7.1 文件上传失败排查
现象:部分团队上传超过50MB的PPT文件时报错
排查过程:
- 检查Nginx配置发现client_max_body_size默认为1M
- Spring Boot默认文件大小限制为10MB
- 前端axios未设置超时时间
解决方案:
properties复制# application.properties
spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=100MB
7.2 高并发下的评分丢失
现象:路演直播期间多位专家同时评分时部分记录丢失
原因分析:
- 评分接口未做并发控制
- 数据库隔离级别为READ_COMMITTED
- 前端未实现操作队列
优化措施:
- 添加数据库乐观锁
java复制@Update("UPDATE score SET value=#{value}, version=version+1
WHERE id=#{id} AND version=#{version}")
int updateWithVersion(Score score);
- 前端实现请求排队机制
- 增加评分结果实时WebSocket推送
8. 项目演进方向
- 智能评审辅助:基于NLP的申报书自动评分
- 虚拟路演厅:3D场景化展示
- 区块链存证:关键环节上链存证
- 数据分析看板:历年项目趋势分析
实施建议:建议首次部署时先聚焦核心申报评审流程,后续逐步迭代高级功能。特别注意提前与教务处对接学生数据同步接口,避免开赛前集中导入数据压力。