1. 项目背景与核心价值
奖学金评定管理系统是高校教务管理中的关键一环,传统纸质化或半自动化处理方式存在效率低下、数据孤岛、流程不透明等痛点。这套基于SpringBoot+Vue+MyBatis的解决方案,正是针对以下典型场景设计:
- 多维度评审:综合学业成绩、科研成果、社会实践等加权计算
- 跨部门协作:教务处、学工部、财务处等多角色协同审批
- 动态规则配置:支持不同奖学金类型(国家/企业/校级)的差异化评定标准
- 全流程追溯:从学生申报到院系初审再到校级终审的完整留痕
技术选型上采用前后端分离架构,后端SpringBoot提供RESTful API,前端Vue实现动态交互,MyBatis处理复杂SQL映射,MySQL确保事务安全。这种组合在高校信息化系统中已成为主流方案,某211高校实际部署数据显示,使用该系统后:
- 评审周期从平均14天缩短至3天
- 人工核对工作量减少80%
- 学生异议申诉率下降65%
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计解析
2.1 技术栈深度适配
SpringBoot 2.7.x 的选择考虑了:
- 内嵌Tomcat简化部署(对比传统War包部署)
- 自动配置的数据库连接池(默认HikariCP)
- Actuator端点监控(特别关注
/health和/metrics) - 与MyBatis的天然集成(
mybatis-spring-boot-starter)
Vue 2.x 的典型应用场景:
- 动态表单渲染(根据奖学金类型切换字段)
- 基于Element UI的审批工作台
- Vuex管理跨组件状态(如用户权限信息)
MyBatis-Plus 3.5.x 的核心价值:
- 动态表名处理器(应对分表需求)
- 逻辑删除注解(保留历史记录)
- 性能分析插件(定位慢SQL)
2.2 数据库关键设计
MySQL 8.0的表结构设计要点:
sql复制-- 学生基础表
CREATE TABLE `t_student` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '学号',
`college_code` VARCHAR(20) NOT NULL COMMENT '学院编码',
`gpa` DECIMAL(3,2) UNSIGNED NOT NULL COMMENT '平均学分绩',
`research_score` INT UNSIGNED DEFAULT 0 COMMENT '科研得分',
PRIMARY KEY (`id`),
KEY `idx_college` (`college_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-- 奖学金规则表(动态配置核心)
CREATE TABLE `t_scholarship_rule` (
`rule_id` INT NOT NULL AUTO_INCREMENT,
`type` ENUM('NATIONAL','ENTERPRISE','SCHOOL') NOT NULL,
`formula` JSON NOT NULL COMMENT 'JSON格式计算规则',
`start_time` DATETIME NOT NULL,
`end_time` DATETIME NOT NULL,
PRIMARY KEY (`rule_id`),
KEY `idx_type_time` (`type`,`start_time`,`end_time`)
);
特别注意:公式字段采用JSON类型存储,示例值:
json复制{ "base": "gpa*0.7", "extra": { "research": "research_score*0.3", "penalty": "-violation_count*5" } }
3. 核心功能实现细节
3.1 动态规则引擎
采用Groovy脚本解析JSON公式:
java复制// RuleEngineService.java
public BigDecimal calculateTotalScore(Long studentId, String ruleJson) {
Map<String, Object> binding = new HashMap<>();
binding.put("gpa", studentMapper.selectGpa(studentId));
binding.put("research_score", studentMapper.selectResearchScore(studentId));
GroovyShell shell = new GroovyShell(binding);
Script script = shell.parse(ruleJson);
return (BigDecimal) script.run();
}
实际应用中需注意:
- 脚本沙箱安全(禁用System等危险类)
- 预编译缓存(避免重复解析开销)
- 异常处理(公式语法错误捕获)
3.2 审批工作流
基于状态机的审批流程控制:
java复制// ScholarshipApplication.java
public enum ApplicationStatus {
DRAFT, // 草稿
COLLEGE_REJECTED, // 院系驳回
SCHOOL_REJECTED, // 校级驳回
FINISHED; // 终审通过
private static final Map<ApplicationStatus, Set<ApplicationStatus>> transitions = Map.of(
DRAFT, Set.of(COLLEGE_REJECTED, SCHOOL_REJECTED, FINISHED),
COLLEGE_REJECTED, Set.of(DRAFT),
SCHOOL_REJECTED, Set.of(COLLEGE_REJECTED)
);
public boolean canTransitionTo(ApplicationStatus target) {
return transitions.getOrDefault(this, Set.of()).contains(target);
}
}
前端配合实现可视化审批轨迹:
vue复制<!-- ApprovalTimeline.vue -->
<el-timeline>
<el-timeline-item
v-for="(log, index) in auditLogs"
:key="index"
:timestamp="log.operateTime"
:color="getStatusColor(log.status)">
{{ log.operatorName }} {{ getActionText(log.action) }}
</el-timeline-item>
</el-timeline>
4. 部署与性能优化
4.1 高并发场景应对
评审高峰期(如国家奖学金季)需特别注意:
-
MySQL优化:
- 增加连接池大小(建议HikariCP配置)
yaml复制spring: datasource: hikari: maximum-pool-size: 50 connection-timeout: 30000- 为评审结果表添加复合索引
sql复制ALTER TABLE t_review_result ADD INDEX idx_search (scholarship_type, college_code, status); -
缓存策略:
- 使用Redis缓存基础数据(学生信息、规则配置)
- Caffeine本地缓存热点计算公式
4.2 安全防护要点
-
XSS防御:
- 前端使用DOMPurify过滤富文本
javascript复制import DOMPurify from 'dompurify'; this.safeHtml = DOMPurify.sanitize(unsafeHtml);- 后端统一响应处理
java复制@Bean public HttpMessageConverters customConverters() { StringHttpMessageConverter converter = new StringHttpMessageConverter(); converter.setWriteAcceptCharset(false); return new HttpMessageConverters(converter); } -
权限控制:
- 基于注解的细粒度控制
java复制@PreAuthorize("hasRole('COLLEGE_ADMIN') and #collegeCode == authentication.details.collegeCode") public List<Application> getCollegeApplications(String collegeCode) { // ... }
5. 扩展开发建议
5.1 智能审核辅助
集成NLP技术实现:
- 申请书相似度检测(防抄袭)
- 关键信息自动提取(如论文标题、专利号)
- 使用HanLP分词示例:
java复制List<Term> terms = HanLP.segment("基于SpringBoot的奖学金系统设计");
5.2 移动端适配
通过PWA技术实现:
- Service Worker缓存核心API
- Manifest配置桌面图标
- 扫码登录功能集成
vue复制// QrLogin.vue
methods: {
async refreshQr() {
this.qrUrl = await api.generateQrCode();
this.pollLoginStatus();
},
pollLoginStatus() {
const timer = setInterval(async () => {
const res = await api.checkScanStatus(this.qrUrl);
if (res.scanned) clearInterval(timer);
}, 2000);
}
}
6. 常见问题排查
6.1 MyBatis日志捕获
使用Arthas监控SQL:
bash复制# 启动Arthas
java -jar arthas-boot.jar
# 监控Mapper接口
watch com.example.mapper.* * '{params,returnObj}' -x 3
6.2 事务失效场景
典型case处理:
java复制// 错误示例:同类调用导致@Transactional失效
public void processApplication(Long id) {
this.updateStatus(id); // 不生效
}
// 正确做法:自注入或拆分Service
@Autowired
private ApplicationService self;
public void processApplication(Long id) {
self.updateStatus(id);
}
7. 二次开发指南
7.1 自定义公式变量
扩展规则引擎的步骤:
- 在
t_student表添加新字段 - 修改Groovy脚本绑定逻辑
- 前端动态表单配置界面
vue复制<template>
<el-form-item
v-for="(var, index) in variables"
:key="index"
:label="var.label">
<el-input v-model="var.expression" />
</el-form-item>
</template>
7.2 多数据源集成
对接Oracle历史数据:
java复制@Configuration
@MapperScan(
basePackages = "com.example.oracle",
sqlSessionFactoryRef = "oracleSqlSessionFactory")
public class OracleDataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.oracle")
public DataSource oracleDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public SqlSessionFactory oracleSqlSessionFactory(
@Qualifier("oracleDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(
new PathMatchingResourcePatternResolver()
.getResources("classpath:mapper/oracle/*.xml"));
return bean.getObject();
}
}
