1. 项目背景与需求分析
高校毕业与学位资格审核是教务管理中的核心环节,传统人工审核方式存在三大痛点:一是面对数千名毕业生的复杂审核规则(如学分要求、课程达标、论文通过等),人工核对极易出错;二是多部门协同效率低下,学生需要往返于院系、教务处等部门;三是历史数据追溯困难,缺乏数字化存档。我们开发的系统正是为了解决这些痛点。
以某高校计算机学院为例,每年毕业季需要审核约800名学生的毕业资格,涉及30余门专业课程、5类素质学分和论文答辩状态。传统方式需要3名教务人员连续工作两周,错误率约2%。而数字化系统可在2天内完成全部审核,准确率100%,同时自动生成审核报告。
2. 技术架构设计
2.1 整体架构方案
采用前后端分离架构,这是现代企业级应用的标准范式。前端使用Vue 3组合式API+TypeScript保证代码健壮性,后端采用Spring Boot 2.7.x+Lombok简化开发,数据库选用MySQL 8.0利用其窗口函数实现复杂统计。技术选型考量:
-
前后端分离优势:
- 并行开发:前端团队可独立进行UI开发,通过Mock数据模拟接口
- 技术栈自由:前后端可分别升级技术栈而不互相影响
- 性能优化:静态资源可通过CDN分发,减轻服务器压力
-
Spring Boot关键配置:
yaml复制# application-prod.yml
spring:
datasource:
url: jdbc:mysql://mysql-cluster:3306/audit_db?useSSL=false&serverTimezone=Asia/Shanghai
hikari:
maximum-pool-size: 20 # 根据压测结果调整
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
2.2 数据库设计精要
2.2.1 核心表关系设计
采用三范式设计原则,通过外键建立关联。特别注意:
-
学生学业表(academic_records):
- 添加status字段标识审核状态(0-未开始 1-初审中 2-复审中 3-已完成)
- 建立复合索引(student_code, major_field)加速查询
-
**课程成绩表(course_scores)**创新设计:
sql复制CREATE TABLE `course_scores` (
`score_id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`course_code` VARCHAR(20) NOT NULL COMMENT '课程编码规则:专业缩写+年份+序号',
`student_code` VARCHAR(20) NOT NULL,
`score_type` TINYINT DEFAULT 1 COMMENT '1-正常考试 2-补考 3-重修',
`effective_score` DECIMAL(5,2) GENERATED ALWAYS AS (
CASE WHEN score_type=1 THEN score_value
WHEN score_type IN (2,3) THEN LEAST(score_value,60)
END
) STORED,
FOREIGN KEY (student_code) REFERENCES academic_records(student_code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
这里使用生成列自动处理补考成绩最高60分的业务规则。
2.2.2 审核流程表设计
采用状态机模式设计审核流程:
java复制public enum AuditStatus {
INIT(0, "未提交"),
DEPARTMENT_REVIEW(1, "院系审核"),
ACADEMIC_REVIEW(2, "教务处审核"),
FINAL_APPROVAL(3, "学位委员会审批"),
REJECTED(-1, "已驳回");
private final int code;
private final String desc;
// ...
}
配合历史记录表实现完整审计追踪:
sql复制CREATE TABLE audit_logs (
log_id BIGINT PRIMARY KEY,
audit_id BIGINT NOT NULL,
from_status INT NOT NULL,
to_status INT NOT NULL,
operator VARCHAR(50) NOT NULL,
comment TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
3. 核心功能实现
3.1 自动化审核引擎
3.1.1 规则配置化设计
采用JSON Schema定义审核规则,例如计算机专业的毕业要求:
json复制{
"ruleName": "CS_BACHELOR_2023",
"requiredCredits": 160,
"coreCourses": [
{"courseCode": "CS101", "minScore": 60},
{"courseCode": "CS203", "minScore": 70}
],
"electiveGroups": [
{
"groupName": "AI方向",
"selectAtLeast": 2,
"courses": ["CS301","CS302","CS303"]
}
],
"thesisRequired": true
}
规则引擎处理流程:
- 加载专业对应规则模板
- 查询学生成绩数据
- 执行规则校验
- 生成审核报告
3.1.2 高性能批量处理
使用Spring Batch处理大规模审核:
java复制@Bean
public Job graduationAuditJob() {
return jobBuilderFactory.get("graduationAudit")
.start(stepBuilderFactory.get("prepareData")
.tasklet(prepareTasklet)
.build())
.next(stepBuilderFactory.get("processAudit")
.<Student, AuditResult>chunk(100)
.reader(auditItemReader)
.processor(auditProcessor)
.writer(auditWriter)
.faultTolerant()
.skipPolicy(new AlwaysSkipPolicy())
.build())
.build();
}
实测数据:处理1000名学生数据约需90秒(服务器配置:4核8G)
3.2 多级审核流程
3.2.1 动态流程配置
采用Activiti工作流引擎实现可配置流程:
xml复制<process id="degreeAuditProcess">
<startEvent id="start"/>
<userTask id="departmentReview" name="院系初审"/>
<exclusiveGateway id="gateway1"/>
<userTask id="academicReview" name="教务处复核"/>
<endEvent id="end"/>
<sequenceFlow sourceRef="start" targetRef="departmentReview"/>
<sequenceFlow sourceRef="departmentReview" targetRef="gateway1"/>
<sequenceFlow sourceRef="gateway1" targetRef="academicReview"
conditionExpression="${result=='PASS'}"/>
<sequenceFlow sourceRef="gateway1" targetRef="end"
conditionExpression="${result=='REJECT'}"/>
</process>
3.2.2 实时消息通知
集成WebSocket实现审核提醒:
vue复制// 前端订阅消息
const socket = new SockJS('/audit-websocket');
const stompClient = Stomp.over(socket);
stompClient.connect({}, () => {
stompClient.subscribe('/topic/audit-notice', (message) => {
this.$notify({
title: '新审核任务',
message: JSON.parse(message.body).content,
type: 'warning'
});
});
});
4. 前端工程实践
4.1 管理端功能模块
采用Vue3+Element Plus构建,核心功能组件:
- 学生信息看板:使用ECharts实现学分分布雷达图
- 批量导入组件:支持Excel模板下载与上传
- 审核详情页:Diff对比显示历史修改记录
关键代码片段:
vue复制<script setup>
// 组合式API实现审核逻辑
const auditResult = ref('');
const handleAudit = async (action) => {
const { data } = await axios.post('/api/audit', {
studentId: props.studentId,
action: action,
comment: auditResult.value
});
emit('audited', data);
};
</script>
4.2 学生端特色功能
-
智能预审功能:
- 实时计算当前学分达成度
- 可视化显示未达标课程
- 生成个性化补修建议
-
材料上传组件:
vue复制<template>
<el-upload
action="/api/upload"
:before-upload="checkFile"
:on-success="handleSuccess">
<template #tip>
<div class="text-xs text-gray-500">
支持PDF/JPEG格式,单个文件不超过5MB
</div>
</template>
</el-upload>
</template>
5. 系统部署方案
5.1 容器化部署
使用Docker Compose编排服务:
yaml复制version: '3.8'
services:
backend:
build: ./backend
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
depends_on:
- mysql
- redis
frontend:
build: ./frontend
ports:
- "80:80"
mysql:
image: mysql:8.0
volumes:
- mysql_data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=audit@123
- MYSQL_DATABASE=audit_db
volumes:
mysql_data:
5.2 性能优化措施
-
缓存策略:
- 使用Redis缓存热门查询(如专业规则)
- 实现二级缓存:Caffeine本地缓存+Redis分布式缓存
-
SQL优化示例:
java复制@Repository
public interface ScoreRepository extends JpaRepository<CourseScore, Long> {
@Query(value = """
SELECT s.course_code, AVG(s.effective_score) as avg_score
FROM course_scores s
WHERE s.student_code IN (
SELECT a.student_code FROM academic_records a
WHERE a.major_field = ?1 AND a.enrollment_date = ?2
)
GROUP BY s.course_code
""", nativeQuery = true)
List<Map<String, Object>> findMajorAvgScores(String major, LocalDate enrollmentYear);
}
6. 开发经验总结
6.1 典型问题解决方案
- 并发审核冲突:
采用乐观锁机制:
java复制@Transactional
public AuditResult submitAudit(Long recordId, AuditRequest request) {
AcademicRecord record = recordRepository.findById(recordId)
.orElseThrow(() -> new ResourceNotFoundException("记录不存在"));
if (record.getVersion() != request.getVersion()) {
throw new OptimisticLockException("数据已被其他审核人修改");
}
// 处理审核逻辑
record.setStatus(request.getStatus());
return auditRepository.save(record);
}
- 复杂规则解析:
使用ANTLR实现自定义规则DSL:
g4复制grammar AuditRule;
ruleSet: 'REQUIRE' creditRule (',' creditRule)*;
creditRule: courseRule | creditRule;
courseRule: COURSE_CODE ('>'|'<') INT;
CREDIT: 'CREDIT';
COURSE_CODE: [A-Z]{2,3}[0-9]{3};
6.2 项目演进方向
-
智能分析扩展:
- 使用PyTorch构建学业预警模型
- 集成NLP处理审核意见文本分析
-
生态集成:
- 对接学校统一身份认证
- 与教务系统实时数据同步
在开发过程中,我们发现MyBatis的动态SQL在处理复杂条件查询时比JPA更灵活,特别是在多表关联统计场景下。建议在类似项目中:
- 简单CRUD使用JPA提高开发效率
- 复杂报表查询使用MyBatis手动优化SQL
- 混合方案可通过Spring Data JPA + MyBatis共同实现