23 KiB
23 KiB
奖学金申请管理模块需求设计 v2.0
版本: v2.0
更新时间: 2025-01-01
文档说明: 基于班主任代学生申请模式的重新设计
📋 1. 需求概述
1.1 背景说明
基于实际业务需求调研,奖学金申请流程需要调整为:
- 班主任代申请模式:不再是学生自主申请,而是由班主任从班级学生中选择推荐
- 材料上传管理:班主任可以为每个推荐学生上传申请材料(非必填)
- 名额控制机制:严格按照班级或学院分配的名额进行申请限制
- 时间窗口控制:只能在批次开放的时间段内进行申请操作
1.2 核心变更点
| 变更点 | 原设计 | 新设计 |
|---|---|---|
| 申请主体 | 学生自主申请 | 班主任代学生申请 |
| 申请方式 | 学生在线填写申请表 | 班主任从班级学生中选择 |
| 材料上传 | 学生自行上传 | 班主任统一管理上传 |
| 条件过滤 | 系统自动过滤 | 暂时不做申请条件过滤 |
| 名额控制 | 按院系统计控制 | 按班级→学院层级控制 |
👥 2. 角色权限设计
2.1 角色定义
| 角色 | 申请管理权限 | 主要操作 |
|---|---|---|
| 班主任 | 本班级学生申请管理 | 选择学生、上传材料、提交申请 |
| 学院管理员 | 本学院申请审核管理 | 查看申请、审核、统计 |
| 学生处管理员 | 全校申请统计管理 | 全局统计、结果确认 |
| 学生 | 查看自己申请状态 | 查看申请进度、结果 |
2.2 权限矩阵
| 功能模块 | 班主任 | 学院管理员 | 学生处管理员 | 学生 |
|---|---|---|---|---|
| 学生选择推荐 | ✏️ | 🔍 | 🔍 | ❌ |
| 材料上传管理 | ✏️ | 🔍 | 🔍 | ❌ |
| 申请提交 | ✏️ | ❌ | ❌ | ❌ |
| 申请审核 | 🔍 | ✏️ | ✏️ | ❌ |
| 申请状态查看 | ✅ | ✅ | ✅ | 🔍 |
| 统计报表 | 🔍 | ✏️ | ✅ | ❌ |
图例: ✅全部权限 ✏️编辑权限 🔍查看权限 ❌无权限
🔧 3. 功能模块设计
3.1 班主任申请管理
3.1.1 学生选择功能
功能描述: 班主任从本班级学生中选择推荐申请奖学金的学生
核心逻辑:
1. 获取班级学生列表(显示基本信息:学号、姓名、专业)
2. 支持多选学生(暂不做申请条件自动过滤)
3. 实时显示已选择学生数量 vs 可申请名额
4. 名额控制:优先使用班级分配名额,无班级名额时使用学院名额
5. 提供学生基本信息预览(便于班主任选择判断)
界面要求:
- 学生列表表格:学号、姓名、专业、在校状态
- 批量选择操作:全选、反选、清空
- 名额提示:
已选择 X 人,可申请名额 Y 人 - 学生详情弹窗:点击学生姓名显示详细信息
3.1.2 材料上传管理
功能描述: 班主任为每个推荐学生上传申请材料
核心逻辑:
1. 已选择学生的材料管理列表
2. 支持每个学生上传多个材料文件
3. 材料分类管理:成绩单、获奖证书、其他证明
4. 文件格式限制:PDF、JPG、PNG,单文件不超过10MB
5. 材料状态标识:已上传、未上传(材料上传为非必填)
界面要求:
- 学生材料管理表格:学生信息、材料数量、上传状态、操作
- 材料上传弹窗:支持拖拽上传、批量上传
- 材料预览功能:支持在线预览已上传材料
- 进度提示:
X 人已上传材料,Y 人未上传
3.1.3 申请提交控制
功能描述: 班主任统一提交本班级所有推荐学生的申请
核心逻辑:
1. 时间窗口检查:必须在批次申请开放时间内
2. 名额数量检查:推荐学生数不能超过分配名额
3. 名额分配检查:班级有名额优先使用,无班级名额时使用学院名额
4. 批量生成申请记录:每个学生生成一条申请记录
5. 状态更新:申请提交后不能修改,除非撤回
提交前验证:
- ✅ 批次申请时间有效性
- ✅ 推荐学生数量 ≤ 可用名额
- ✅ 学生信息完整性
- ⚠️ 材料上传完整性(提示但不强制)
3.2 名额控制机制
3.2.1 层级名额分配
全校总名额
├── 学院A名额
│ ├── 班级A1名额 (优先使用)
│ ├── 班级A2名额
│ └── 学院A机动名额 (班级无名额时使用)
└── 学院B名额
├── 班级B1名额
└── 学院B机动名额
3.2.2 名额使用逻辑
申请时名额检查顺序:
- 班级名额优先: 如果班级有分配名额,优先使用班级名额
- 学院名额兜底: 如果班级无名额,使用学院级别名额
- 名额不足提示: 超过可用名额时给出明确提示
- 实时名额更新: 申请提交后立即更新已用名额
名额计算公式:
-- 班级可用名额计算
班级可用名额 = 班级总名额 - 班级已用名额 - 班级预留名额
-- 学院可用名额计算(当班级无名额时)
学院可用名额 = 学院总名额 - 学院已用名额 - 学院预留名额
3.3 时间窗口控制
3.3.1 申请时间控制
// 申请时间检查逻辑
public boolean checkApplicationTimeWindow(Long batchId) {
ScholarshipBatch batch = batchService.getById(batchId);
Date now = new Date();
// 检查批次状态
if (!"ACTIVE".equals(batch.getStatus())) {
return false;
}
// 检查申请时间窗口
return now.after(batch.getApplicationStartTime())
&& now.before(batch.getApplicationEndTime());
}
3.3.2 操作权限控制
| 操作 | 申请开始前 | 申请期间 | 申请结束后 |
|---|---|---|---|
| 选择学生 | ❌ | ✅ | ❌ |
| 上传材料 | ❌ | ✅ | 🔍(仅查看) |
| 提交申请 | ❌ | ✅ | ❌ |
| 撤回申请 | ❌ | ✅ | ❌ |
| 查看状态 | ✅ | ✅ | ✅ |
📊 4. 数据模型设计
4.1 申请记录表调整
基于新需求,需要调整现有的申请记录表结构:
-- 修改申请记录表
ALTER TABLE jcbt_scholarship_application
ADD COLUMN `applicant_type` VARCHAR(20) DEFAULT 'TEACHER' COMMENT '申请人类型:STUDENT-学生申请,TEACHER-教师代申请';
ALTER TABLE jcbt_scholarship_application
ADD COLUMN `applicant_id` BIGINT(20) DEFAULT NULL COMMENT '申请人ID(班主任ID)';
ALTER TABLE jcbt_scholarship_application
ADD COLUMN `applicant_name` VARCHAR(100) DEFAULT NULL COMMENT '申请人姓名(班主任姓名)';
-- 修改申请类型枚举值
ALTER TABLE jcbt_scholarship_application
MODIFY COLUMN `application_type` VARCHAR(20) NOT NULL
COMMENT '申请类型:TEACHER_RECOMMEND-教师推荐,AUTO-自动评定,DIRECT-直接指定';
-- 添加班级信息索引
CREATE INDEX idx_class_batch ON jcbt_scholarship_application(class_id, batch_id);
CREATE INDEX idx_applicant_batch ON jcbt_scholarship_application(applicant_id, batch_id);
4.2 班级名额分配表
新增班级级别的名额分配管理:
-- 班级名额分配表
CREATE TABLE jcbt_scholarship_class_quota (
id BIGINT(20) NOT NULL COMMENT '主键ID',
batch_id BIGINT(20) NOT NULL COMMENT '批次ID',
scholarship_type_id BIGINT(20) NOT NULL COMMENT '奖学金类型ID',
dept_id BIGINT(20) NOT NULL COMMENT '学院ID',
class_id BIGINT(20) NOT NULL COMMENT '班级ID',
class_name VARCHAR(100) NOT NULL COMMENT '班级名称',
total_quota INT DEFAULT 0 COMMENT '总名额',
used_quota INT DEFAULT 0 COMMENT '已用名额',
reserved_quota INT DEFAULT 0 COMMENT '预留名额',
available_quota INT DEFAULT 0 COMMENT '可用名额',
allocation_method VARCHAR(20) DEFAULT 'MANUAL' COMMENT '分配方式:MANUAL-手动分配,AUTO-自动分配',
is_locked TINYINT(1) DEFAULT 0 COMMENT '是否锁定:0-否,1-是',
status VARCHAR(20) DEFAULT 'ACTIVE' COMMENT '状态:ACTIVE-有效,INACTIVE-无效',
remark VARCHAR(500) DEFAULT NULL COMMENT '备注',
tenant_id BIGINT(20) NOT NULL COMMENT '租户ID',
create_by BIGINT(20) DEFAULT NULL COMMENT '创建者',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_by BIGINT(20) DEFAULT NULL COMMENT '更新者',
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
deleted TINYINT(1) DEFAULT 0 COMMENT '删除标记:0-正常,1-删除',
PRIMARY KEY (id),
UNIQUE KEY uk_batch_type_class (batch_id, scholarship_type_id, class_id, deleted),
INDEX idx_dept_class (dept_id, class_id),
INDEX idx_batch_dept (batch_id, dept_id),
INDEX idx_quota_status (total_quota, status),
INDEX idx_tenant (tenant_id, deleted)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='班级名额分配表';
4.3 申请材料表调整
调整材料表以支持班主任上传:
-- 添加上传者信息
ALTER TABLE jcbt_scholarship_attachment
ADD COLUMN `uploader_type` VARCHAR(20) DEFAULT 'TEACHER' COMMENT '上传者类型:STUDENT-学生,TEACHER-教师';
ALTER TABLE jcbt_scholarship_attachment
ADD COLUMN `uploader_id` BIGINT(20) DEFAULT NULL COMMENT '上传者ID';
ALTER TABLE jcbt_scholarship_attachment
ADD COLUMN `uploader_name` VARCHAR(100) DEFAULT NULL COMMENT '上传者姓名';
-- 修改必需字段逻辑
ALTER TABLE jcbt_scholarship_attachment
MODIFY COLUMN `is_required` TINYINT(1) DEFAULT 0 COMMENT '是否必需:0-否,1-是(新需求中材料非必填)';
4.4 名额使用记录表
新增名额使用记录表,用于追踪名额使用情况:
-- 名额使用记录表
CREATE TABLE jcbt_scholarship_quota_usage (
id BIGINT(20) NOT NULL COMMENT '主键ID',
batch_id BIGINT(20) NOT NULL COMMENT '批次ID',
scholarship_type_id BIGINT(20) NOT NULL COMMENT '奖学金类型ID',
quota_type VARCHAR(20) NOT NULL COMMENT '名额类型:CLASS-班级名额,DEPT-学院名额',
target_id BIGINT(20) NOT NULL COMMENT '目标ID(班级ID或学院ID)',
application_id BIGINT(20) NOT NULL COMMENT '申请ID',
student_id BIGINT(20) NOT NULL COMMENT '学生ID',
operation_type VARCHAR(20) NOT NULL COMMENT '操作类型:USE-使用,RELEASE-释放',
operation_time DATETIME NOT NULL COMMENT '操作时间',
operator_id BIGINT(20) NOT NULL COMMENT '操作人ID',
operator_name VARCHAR(100) NOT NULL COMMENT '操作人姓名',
remark VARCHAR(500) DEFAULT NULL COMMENT '备注',
tenant_id BIGINT(20) NOT NULL COMMENT '租户ID',
create_by BIGINT(20) DEFAULT NULL COMMENT '创建者',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_by BIGINT(20) DEFAULT NULL COMMENT '更新者',
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
deleted TINYINT(1) DEFAULT 0 COMMENT '删除标记:0-正常,1-删除',
PRIMARY KEY (id),
INDEX idx_batch_type_target (batch_id, scholarship_type_id, target_id),
INDEX idx_application_student (application_id, student_id),
INDEX idx_operation_time (operation_type, operation_time),
INDEX idx_tenant (tenant_id, deleted)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='名额使用记录表';
🔄 5. 业务流程设计
5.1 申请提交流程
graph TD
A[班主任登录] --> B[选择申请批次]
B --> C[检查申请时间窗口]
C --> D{时间窗口有效?}
D -->|否| E[提示申请时间未开放]
D -->|是| F[获取班级学生列表]
F --> G[选择推荐学生]
G --> H[检查名额限制]
H --> I{名额足够?}
I -->|否| J[提示名额不足]
I -->|是| K[上传学生材料]
K --> L[确认提交申请]
L --> M[生成申请记录]
M --> N[更新名额使用]
N --> O[发送提交通知]
5.2 名额检查流程
graph TD
A[开始名额检查] --> B[获取班级分配名额]
B --> C{班级有分配名额?}
C -->|是| D[计算班级可用名额]
C -->|否| E[获取学院分配名额]
D --> F{班级名额足够?}
F -->|是| G[使用班级名额]
F -->|否| E
E --> H[计算学院可用名额]
H --> I{学院名额足够?}
I -->|是| J[使用学院名额]
I -->|否| K[提示名额不足]
G --> L[允许申请]
J --> L
K --> M[拒绝申请]
5.3 材料管理流程
graph TD
A[进入材料管理] --> B[显示已选学生列表]
B --> C[选择学生上传材料]
C --> D[检查文件格式]
D --> E{格式有效?}
E -->|否| F[提示格式错误]
E -->|是| G[上传文件到服务器]
G --> H[保存材料记录]
H --> I[更新材料状态]
I --> J[显示上传成功]
J --> K{还有其他学生?}
K -->|是| C
K -->|否| L[完成材料上传]
📋 6. 接口设计
6.1 学生选择接口
/**
* 获取班级学生列表(供选择推荐)
*/
@GetMapping("/class-students")
public R<List<StudentSelectVo>> getClassStudents(
@RequestParam Long classId,
@RequestParam Long batchId,
@RequestParam Long scholarshipTypeId) {
// 返回班级学生列表,包含基本信息和是否已申请状态
}
/**
* 检查申请名额限制
*/
@PostMapping("/check-quota")
public R<QuotaCheckVo> checkQuota(
@RequestBody QuotaCheckBo quotaCheckBo) {
// 检查选择的学生数量是否超过可用名额
}
6.2 申请提交接口
/**
* 批量提交学生申请
*/
@PostMapping("/batch-submit")
public R<BatchSubmitVo> batchSubmitApplications(
@RequestBody BatchApplicationBo batchApplicationBo) {
// 批量创建申请记录,更新名额使用情况
}
/**
* 撤回班级申请
*/
@PostMapping("/withdraw-batch")
public R<Void> withdrawBatchApplications(
@RequestParam Long classId,
@RequestParam Long batchId,
@RequestParam Long scholarshipTypeId) {
// 撤回班级所有申请,释放名额
}
6.3 材料管理接口
/**
* 上传学生申请材料
*/
@PostMapping("/upload-material")
public R<MaterialUploadVo> uploadStudentMaterial(
@RequestParam Long applicationId,
@RequestParam MultipartFile file,
@RequestParam String materialType) {
// 上传单个学生的申请材料
}
/**
* 获取学生材料列表
*/
@GetMapping("/student-materials")
public R<List<MaterialVo>> getStudentMaterials(
@RequestParam Long applicationId) {
// 获取指定申请的所有材料
}
📊 7. 前端页面设计
7.1 申请管理主页面
页面结构:
[批次选择] [奖学金类型选择]
==========================================
申请状态: [时间窗口状态] [名额统计]
==========================================
学生选择区域:
┌─────────────────────────────────────┐
│ [全选] [反选] [清空] 已选择X人/可申请Y人 │
├─────────────────────────────────────┤
│ ☐ 张三 (2021001) 计算机科学与技术 │
│ ☑ 李四 (2021002) 软件工程 │
│ ☐ 王五 (2021003) 信息安全 │
└─────────────────────────────────────┘
==========================================
[上传材料] [提交申请] [撤回申请]
7.2 材料管理页面
页面结构:
材料上传管理
==========================================
┌─学生─┬─材料数量─┬─上传状态─┬─操作─┐
│ 张三 │ 2 │ 已完成 │ 查看 │
│ 李四 │ 0 │ 未上传 │ 上传 │
│ 王五 │ 1 │ 部分 │ 管理 │
└─────┴────────┴────────┴──────┘
==========================================
进度: 2人已上传材料,1人未上传
7.3 申请状态查看页面
页面结构:
申请状态总览
==========================================
批次: 2024年春季学期 | 类型: 国家奖学金
申请时间: 2024-03-01 ~ 2024-03-31
名额情况: 班级名额 2/3,学院名额 15/20
==========================================
申请学生列表:
┌─学号───┬─姓名─┬─状态───┬─材料─┬─操作─┐
│2021001 │ 张三 │ 待审核 │ 2 │ 查看 │
│2021002 │ 李四 │ 已通过 │ 0 │ 查看 │
└────────┴─────┴────────┴──────┴──────┘
🔧 8. 技术实现要点
8.1 名额控制实现
@Service
public class QuotaControlService {
/**
* 检查并分配名额
*/
public QuotaAllocationResult allocateQuota(QuotaAllocationBo request) {
// 1. 检查班级名额
QuotaVo classQuota = getClassQuota(request.getClassId(),
request.getBatchId(), request.getScholarshipTypeId());
if (classQuota != null && classQuota.getAvailableQuota() >= request.getStudentCount()) {
// 使用班级名额
return allocateClassQuota(request, classQuota);
}
// 2. 检查学院名额
QuotaVo deptQuota = getDeptQuota(request.getDeptId(),
request.getBatchId(), request.getScholarshipTypeId());
if (deptQuota != null && deptQuota.getAvailableQuota() >= request.getStudentCount()) {
// 使用学院名额
return allocateDeptQuota(request, deptQuota);
}
// 3. 名额不足
throw new BusinessException("可用名额不足");
}
}
8.2 时间窗口控制
@Component
public class ApplicationTimeValidator {
@Autowired
private ScholarshipBatchService batchService;
/**
* 验证申请时间窗口
*/
public void validateApplicationTime(Long batchId) {
ScholarshipBatch batch = batchService.getById(batchId);
Date now = new Date();
// 检查批次状态
if (!"ACTIVE".equals(batch.getStatus())) {
throw new BusinessException("当前批次未开放申请");
}
// 检查申请开始时间
if (now.before(batch.getApplicationStartTime())) {
throw new BusinessException("申请尚未开始,开始时间:" +
DateUtils.formatDate(batch.getApplicationStartTime()));
}
// 检查申请结束时间
if (now.after(batch.getApplicationEndTime())) {
throw new BusinessException("申请已结束,结束时间:" +
DateUtils.formatDate(batch.getApplicationEndTime()));
}
}
}
8.3 批量申请提交
@Service
@Transactional(rollbackFor = Exception.class)
public class BatchApplicationService {
/**
* 批量提交申请
*/
public BatchSubmitResult batchSubmitApplications(BatchApplicationBo request) {
// 1. 验证申请时间
applicationTimeValidator.validateApplicationTime(request.getBatchId());
// 2. 分配名额
QuotaAllocationResult quotaResult = quotaControlService.allocateQuota(request);
// 3. 批量创建申请记录
List<ScholarshipApplication> applications = request.getStudentIds().stream()
.map(studentId -> buildApplication(request, studentId, quotaResult))
.collect(Collectors.toList());
scholarshipApplicationService.saveBatch(applications);
// 4. 更新名额使用情况
updateQuotaUsage(quotaResult);
// 5. 记录操作日志
logBatchOperation(request, applications);
return BatchSubmitResult.success(applications.size());
}
}
📝 9. 测试用例设计
9.1 功能测试用例
| 测试场景 | 测试步骤 | 预期结果 |
|---|---|---|
| 正常申请流程 | 1.选择学生 2.上传材料 3.提交申请 | 申请成功,名额正确扣减 |
| 名额不足 | 选择学生数量超过可用名额 | 提示名额不足,禁止提交 |
| 时间窗口外申请 | 在申请时间外进行操作 | 提示时间窗口错误 |
| 材料上传 | 上传各种格式文件 | 正确文件上传成功,错误格式拒绝 |
| 申请撤回 | 提交后撤回申请 | 申请状态更新,名额释放 |
9.2 性能测试用例
| 测试场景 | 并发数 | 数据量 | 性能要求 |
|---|---|---|---|
| 批量申请提交 | 50 | 100人/班 | 响应时间<3秒 |
| 学生列表查询 | 100 | 10000学生 | 响应时间<1秒 |
| 材料上传 | 20 | 10MB文件 | 上传成功率>99% |
📚 10. 部署说明
10.1 数据库升级脚本
- 执行申请表结构调整脚本
- 创建班级名额分配表
- 创建名额使用记录表
- 更新相关索引
10.2 配置项调整
# application.yml
scholarship:
application:
# 材料上传配置
material:
max-file-size: 10MB
allowed-types: pdf,jpg,jpeg,png
upload-path: /data/scholarship/materials/
# 名额控制配置
quota:
check-enabled: true
auto-allocation: true
# 时间窗口配置
time-window:
strict-check: true
buffer-minutes: 30
📋 11. 总结
11.1 主要改进点
- 申请模式优化: 从学生自申请改为班主任代申请,提高管理效率
- 名额控制增强: 实现班级→学院两级名额管理,更精确的控制
- 材料管理简化: 班主任统一管理,降低学生操作复杂度
- 时间窗口严格控制: 确保申请在规定时间内进行
11.2 技术创新点
- 层级名额算法: 智能的班级→学院名额分配算法
- 批量操作优化: 高效的批量申请提交和撤回机制
- 实时状态同步: 名额使用情况实时更新
- 操作日志完整: 完整的操作追踪和审计功能
11.3 下一步计划
- Phase 1: 完成核心申请管理功能开发
- Phase 2: 增加申请条件自动过滤功能
- Phase 3: 完善统计报表和数据导出
- Phase 4: 优化用户体验和性能调优
文档维护: 本文档将随着需求变更和系统开发进展持续更新
最后更新: 2025-01-01
文档版本: v2.0