wuzhen update

This commit is contained in:
wuzhen committed 2025-08-10 00:24:31 +08:00
1 parent bab7b53074
commit a2222f63cb
284 files changed
+48629 -3473

No files matched your search

@@ -0,0 +1,259 @@
# 后端API数据格式示例 - 班级名额显示功能
**创建时间**: 2025-01-27
**功能**: 班主任批量申请奖学金页面显示班级名额和全校名额
**接口**: `getScholarshipTypesWithQuota(batchId, classId)`
## 📋 接口说明
### 接口路径
```
GET /jcbt/scholarshipApplication/scholarshipTypesWithQuota
```
### 请求参数
```json
{
"batchId": "批次ID",
"classId": "班级ID"
}
```
## 🎯 返回数据结构
### 完整数据格式
```json
{
"code": 200,
"msg": "success",
"data": [
{
"id": 1,
"name": "国家奖学金",
"amount": 8000,
"levelType": "国家级",
"typeCategory": "奖学金",
// 班级名额信息(优先显示)
"classQuota": {
"hasQuota": true,
"totalQuota": 5,
"usedQuota": 2,
"availableQuota": 3,
"quotaStatus": "available"
},
// 全校名额信息(参考显示)
"schoolQuota": {
"hasQuota": true,
"totalQuota": 100,
"usedQuota": 30,
"availableQuota": 70,
"quotaStatus": "available"
}
},
{
"id": 2,
"name": "省政府奖学金",
"amount": 6000,
"levelType": "省级",
"typeCategory": "奖学金",
// 班级名额已满的情况
"classQuota": {
"hasQuota": true,
"totalQuota": 2,
"usedQuota": 2,
"availableQuota": 0,
"quotaStatus": "full"
},
"schoolQuota": {
"hasQuota": true,
"totalQuota": 50,
"usedQuota": 35,
"availableQuota": 15,
"quotaStatus": "available"
}
},
{
"id": 3,
"name": "学院奖学金",
"amount": 2000,
"levelType": "校级",
"typeCategory": "奖学金",
// 无班级名额限制,只有全校名额
"classQuota": null,
"schoolQuota": {
"hasQuota": false,
"totalQuota": 0,
"usedQuota": 0,
"availableQuota": 0,
"quotaStatus": "unlimited"
}
}
]
}
```
## 🔧 数据字段说明
### 基础字段
| 字段名 | 类型 | 说明 |
|--------|------|------|
| id | Long | 奖学金类型ID |
| name | String | 奖学金名称 |
| amount | BigDecimal | 奖学金金额 |
| levelType | String | 等级类型(国家级、省级、校级等) |
| typeCategory | String | 类型分类 |
### 班级名额字段 (classQuota)
| 字段名 | 类型 | 说明 |
|--------|------|------|
| hasQuota | Boolean | 是否有班级名额限制 |
| totalQuota | Integer | 班级总名额 |
| usedQuota | Integer | 班级已用名额 |
| availableQuota | Integer | 班级可用名额 |
| quotaStatus | String | 班级名额状态 |
### 全校名额字段 (schoolQuota)
| 字段名 | 类型 | 说明 |
|--------|------|------|
| hasQuota | Boolean | 是否有全校名额限制 |
| totalQuota | Integer | 全校总名额 |
| usedQuota | Integer | 全校已用名额 |
| availableQuota | Integer | 全校可用名额 |
| quotaStatus | String | 全校名额状态 |
## 📊 名额状态说明
### quotaStatus 枚举值
| 状态值 | 说明 | 前端显示 |
|--------|------|----------|
| available | 有可用名额 | 绿色标签 "可申请" |
| full | 名额已满 | 橙色标签 "已满" |
| unlimited | 无名额限制 | 蓝色标签 "无限制" |
## 🎨 前端显示逻辑
### 1. 标签颜色优先级
```typescript
// 优先基于班级名额状态
if (type.classQuota && type.classQuota.hasQuota) {
return type.classQuota.quotaStatus === 'available' ? 'success' : 'warning';
}
// 其次基于全校名额状态
if (type.schoolQuota) {
return type.schoolQuota.quotaStatus === 'unlimited' ? 'info' :
type.schoolQuota.quotaStatus === 'available' ? 'success' : 'warning';
}
```
### 2. 可选择性判断
```typescript
// 优先基于班级名额
if (type.classQuota && type.classQuota.hasQuota) {
return type.classQuota.availableQuota > 0;
}
// 其次基于全校名额
if (type.schoolQuota) {
return type.schoolQuota.quotaStatus === 'unlimited' ||
type.schoolQuota.availableQuota > 0;
}
```
### 3. 显示文本格式
```
班级名额: 3/5 | 全校名额: 70/100
班级名额: 0/2 (已满) | 全校名额: 15/50
全校名额: 无限制
```
## 🚨 重要说明
### 数据一致性要求
1. **班级名额计算**: `availableQuota = totalQuota - usedQuota`
2. **状态同步**: `quotaStatus` 必须与实际名额数量一致
3. **实时性**: 名额信息应该实时更新,反映当前最新状态
### 兼容性处理
- 如果后端暂时无法提供新格式数据,前端会自动降级到旧格式显示
- 支持 `classQuota` 为 `null` 的情况,此时只显示全校名额
- 保持与现有API的向后兼容性
### 权限控制
- 确保班主任只能看到自己班级的名额分配情况
- 不同班级的名额信息应该隔离
- 接口需要验证 `classId` 与当前用户的权限匹配
## 📝 后端实现建议
### SQL查询示例
```sql
-- 查询班级名额分配情况
SELECT
st.id,
st.name,
st.amount,
st.level_type,
st.type_category,
-- 班级名额信息
cq.total_quota as class_total_quota,
cq.used_quota as class_used_quota,
(cq.total_quota - cq.used_quota) as class_available_quota,
CASE
WHEN cq.total_quota IS NULL THEN NULL
WHEN (cq.total_quota - cq.used_quota) > 0 THEN 'available'
ELSE 'full'
END as class_quota_status,
-- 全校名额信息
sq.total_quota as school_total_quota,
sq.used_quota as school_used_quota,
(sq.total_quota - sq.used_quota) as school_available_quota,
CASE
WHEN sq.has_quota = 0 THEN 'unlimited'
WHEN (sq.total_quota - sq.used_quota) > 0 THEN 'available'
ELSE 'full'
END as school_quota_status
FROM scholarship_type st
LEFT JOIN class_quota cq ON st.id = cq.scholarship_type_id AND cq.class_id = ?
LEFT JOIN school_quota sq ON st.id = sq.scholarship_type_id
WHERE st.batch_id = ?
```
### Java实体类建议
```java
@Data
public class ScholarshipTypeWithQuotaVO {
private Long id;
private String name;
private BigDecimal amount;
private String levelType;
private String typeCategory;
private QuotaInfo classQuota;
private QuotaInfo schoolQuota;
}
@Data
public class QuotaInfo {
private Boolean hasQuota;
private Integer totalQuota;
private Integer usedQuota;
private Integer availableQuota;
private String quotaStatus;
}
```
---
**文档更新**: 2025-01-27
**状态**: 待后端实现
**前端适配**: 已完成
@@ -0,0 +1,570 @@
# 奖学金名额分配管理API文档
**文档版本**: v1.0
**创建时间**: 2025-01-27
**模块名称**: 奖惩补贴系统 - 名额分配管理
**技术栈**: Spring Boot 3.4.6 + MyBatis-Plus
---
## 📋 1. 接口概览
### 1.1 模块说明
奖学金名额分配管理模块提供按批次进行名额分配的核心功能,支持多级分配、自动分配、名额调整等业务场景。
### 1.2 基础信息
- **服务地址**: `http://localhost:8080`
- **接口前缀**: `/jcbt/scholarshipQuota`
- **认证方式**: Bearer Token + Sa-Token
- **数据格式**: JSON
### 1.3 接口列表
| 序号 | 接口名称 | 请求方式 | 路径 | 权限标识 |
|------|----------|----------|------|----------|
| 1 | 分页查询名额分配 | GET | `/list` | `jcbt:scholarshipQuota:list` |
| 2 | 按批次查询名额分配 | GET | `/listByBatch/{batchId}` | `jcbt:scholarshipQuota:list` |
| 3 | 按批次和类型查询 | GET | `/listByBatchAndType` | `jcbt:scholarshipQuota:list` |
| 4 | 查询名额树形结构 | GET | `/tree` | `jcbt:scholarshipQuota:list` |
| 5 | 查询名额使用统计 | GET | `/statistics/{batchId}` | `jcbt:scholarshipQuota:list` |
| 6 | 导出名额分配 | POST | `/export` | `jcbt:scholarshipQuota:export` |
| 7 | 获取详细信息 | GET | `/{id}` | `jcbt:scholarshipQuota:query` |
| 8 | 新增名额分配 | POST | `/` | `jcbt:scholarshipQuota:add` |
| 9 | 修改名额分配 | PUT | `/` | `jcbt:scholarshipQuota:edit` |
| 10 | 删除名额分配 | DELETE | `/{ids}` | `jcbt:scholarshipQuota:remove` |
| 11 | 批量分配名额 | POST | `/batchAllocate` | `jcbt:scholarshipQuota:add` |
| 12 | 调整名额分配 | POST | `/adjust` | `jcbt:scholarshipQuota:edit` |
| 13 | 锁定名额分配 | PUT | `/lock/{id}` | `jcbt:scholarshipQuota:edit` |
| 14 | 自动分配名额 | POST | `/autoAllocate` | `jcbt:scholarshipQuota:edit` |
| 15 | 复制名额分配 | POST | `/copy` | `jcbt:scholarshipQuota:add` |
| 16 | 更新名额使用 | PUT | `/updateUsage/{id}` | `jcbt:scholarshipQuota:edit` |
| 17 | 验证名额分配 | POST | `/validate` | `jcbt:scholarshipQuota:query` |
---
## 🔍 2. 查询类接口
### 2.1 分页查询名额分配列表
**接口描述**: 分页查询奖学金名额分配列表,支持多条件筛选
#### 请求信息
```http
GET /jcbt/scholarshipQuota/list?pageNum=1&pageSize=10&batchId=1&scholarshipTypeId=1
Content-Type: application/json
Authorization: Bearer {token}
clientid: e5cd7e4891bf95d1d19206ce24a7b32e
```
#### 请求参数
```json
{
"pageNum": 1, // 页码(必填)
"pageSize": 10, // 页大小(必填)
"batchId": 1, // 批次ID(可选)
"scholarshipTypeId": 1, // 奖学金类型ID(可选)
"allocationLevel": "COLLEGE", // 分配级别(可选)
"targetDeptId": 101, // 目标部门ID(可选)
"status": "ACTIVE", // 状态(可选)
"isLocked": 0 // 是否锁定(可选)
}
```
#### 响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"total": 25,
"rows": [
{
"id": 1,
"batchId": 1,
"batchName": "2024-2025学年第一学期国家奖学金",
"batchCode": "GJ202401",
"academicYear": "2024-2025",
"semester": 1,
"scholarshipTypeId": 1,
"scholarshipTypeName": "国家奖学金",
"scholarshipLevel": "国家级",
"allocationLevel": "COLLEGE",
"allocationLevelName": "学院",
"targetDeptId": 101,
"targetDeptName": "计算机学院",
"parentQuotaId": null,
"parentDeptName": null,
"totalQuota": 10,
"usedQuota": 3,
"reservedQuota": 1,
"availableQuota": 6,
"allocationRule": null,
"allocationBasis": "按学院学生人数比例分配",
"allocationMethod": "MANUAL",
"allocationMethodName": "手动分配",
"isAdjustable": 1,
"isLocked": 0,
"status": "ACTIVE",
"statusName": "生效",
"remark": "",
"tenantId": 1,
"createBy": 1,
"createTime": "2025-01-27 10:00:00",
"updateBy": 1,
"updateTime": "2025-01-27 10:00:00"
}
]
}
}
```
### 2.2 按批次查询名额分配列表
**接口描述**: 查询指定批次的所有名额分配
#### 请求信息
```http
GET /jcbt/scholarshipQuota/listByBatch/1
Authorization: Bearer {token}
clientid: e5cd7e4891bf95d1d19206ce24a7b32e
```
#### 响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": [
{
"id": 1,
"batchId": 1,
"batchName": "2024-2025学年第一学期国家奖学金",
"scholarshipTypeName": "国家奖学金",
"allocationLevel": "COLLEGE",
"targetDeptName": "计算机学院",
"totalQuota": 10,
"usedQuota": 3,
"availableQuota": 6,
"status": "ACTIVE"
}
]
}
```
### 2.3 查询名额分配树形结构
**接口描述**: 查询指定批次和奖学金类型的名额分配层级结构
#### 请求信息
```http
GET /jcbt/scholarshipQuota/tree?batchId=1&scholarshipTypeId=1
Authorization: Bearer {token}
clientid: e5cd7e4891bf95d1d19206ce24a7b32e
```
#### 响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": [
{
"id": 1,
"allocationLevel": "UNIVERSITY",
"targetDeptName": "全校",
"totalQuota": 100,
"children": [
{
"id": 2,
"allocationLevel": "COLLEGE",
"targetDeptName": "计算机学院",
"totalQuota": 30,
"parentQuotaId": 1,
"children": [
{
"id": 3,
"allocationLevel": "MAJOR",
"targetDeptName": "计算机科学与技术",
"totalQuota": 15,
"parentQuotaId": 2
}
]
}
]
}
]
}
```
### 2.4 查询名额使用统计
**接口描述**: 查询指定批次的名额使用统计信息
#### 请求信息
```http
GET /jcbt/scholarshipQuota/statistics/1
Authorization: Bearer {token}
clientid: e5cd7e4891bf95d1d19206ce24a7b32e
```
#### 响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"totalQuota": 100, // 总名额
"usedQuota": 45, // 已使用名额
"availableQuota": 50, // 可用名额
"usageRate": 0.45, // 使用率
"allocationCount": 15 // 分配记录数
}
}
```
---
## ✏️ 3. 新增修改类接口
### 3.1 新增名额分配
**接口描述**: 创建新的奖学金名额分配记录
#### 请求信息
```http
POST /jcbt/scholarshipQuota
Content-Type: application/json
Authorization: Bearer {token}
clientid: e5cd7e4891bf95d1d19206ce24a7b32e
```
#### 请求参数
```json
{
"batchId": 1, // 批次ID(必填)
"scholarshipTypeId": 1, // 奖学金类型ID(必填)
"allocationLevel": "COLLEGE", // 分配级别(必填)
"targetDeptId": 101, // 目标部门ID(必填)
"parentQuotaId": null, // 上级名额ID(可选)
"totalQuota": 10, // 总名额(必填)
"usedQuota": 0, // 已使用名额(可选,默认0)
"reservedQuota": 1, // 预留名额(可选,默认0)
"allocationRule": "", // 分配规则(可选)
"allocationBasis": "按学院学生人数比例分配", // 分配依据(可选)
"allocationMethod": "MANUAL", // 分配方式(可选,默认MANUAL)
"isAdjustable": 1, // 是否可调整(可选,默认1)
"status": "ACTIVE", // 状态(可选,默认ACTIVE)
"remark": "" // 备注(可选)
}
```
#### 响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": null
}
```
### 3.2 修改名额分配
**接口描述**: 修改已存在的名额分配记录
#### 请求信息
```http
PUT /jcbt/scholarshipQuota
Content-Type: application/json
Authorization: Bearer {token}
clientid: e5cd7e4891bf95d1d19206ce24a7b32e
```
#### 请求参数
```json
{
"id": 1, // 主键ID(必填)
"batchId": 1, // 批次ID(必填)
"scholarshipTypeId": 1, // 奖学金类型ID(必填)
"allocationLevel": "COLLEGE", // 分配级别(必填)
"targetDeptId": 101, // 目标部门ID(必填)
"totalQuota": 12, // 总名额(必填)
"usedQuota": 3, // 已使用名额
"reservedQuota": 1, // 预留名额
"allocationBasis": "调整后的分配依据",
"remark": "名额调整"
}
```
### 3.3 批量分配名额
**接口描述**: 为指定批次和奖学金类型批量创建名额分配
#### 请求信息
```http
POST /jcbt/scholarshipQuota/batchAllocate?batchId=1&scholarshipTypeId=1
Content-Type: application/json
Authorization: Bearer {token}
clientid: e5cd7e4891bf95d1d19206ce24a7b32e
```
#### 请求参数
```json
[
{
"allocationLevel": "COLLEGE",
"targetDeptId": 101,
"totalQuota": 10,
"allocationBasis": "计算机学院分配"
},
{
"allocationLevel": "COLLEGE",
"targetDeptId": 102,
"totalQuota": 8,
"allocationBasis": "软件学院分配"
}
]
```
---
## 🔧 4. 业务操作类接口
### 4.1 调整名额分配
**接口描述**: 在两个名额分配之间调整名额数量
#### 请求信息
```http
POST /jcbt/scholarshipQuota/adjust?fromQuotaId=1&toQuotaId=2&adjustAmount=2&reason=学院需求调整
Authorization: Bearer {token}
clientid: e5cd7e4891bf95d1d19206ce24a7b32e
```
#### 参数说明
- `fromQuotaId`: 源名额分配ID
- `toQuotaId`: 目标名额分配ID
- `adjustAmount`: 调整数量(正整数)
- `reason`: 调整原因
### 4.2 锁定/解锁名额分配
**接口描述**: 锁定或解锁名额分配,锁定后不允许修改
#### 请求信息
```http
PUT /jcbt/scholarshipQuota/lock/1?isLocked=1
Authorization: Bearer {token}
clientid: e5cd7e4891bf95d1d19206ce24a7b32e
```
#### 参数说明
- `id`: 名额分配ID
- `isLocked`: 是否锁定(0-否,1-是)
### 4.3 自动分配名额
**接口描述**: 根据配置的规则自动分配名额
#### 请求信息
```http
POST /jcbt/scholarshipQuota/autoAllocate?batchId=1&scholarshipTypeId=1&allocationRule=按比例分配
Authorization: Bearer {token}
clientid: e5cd7e4891bf95d1d19206ce24a7b32e
```
#### 参数说明
- `batchId`: 批次ID
- `scholarshipTypeId`: 奖学金类型ID
- `allocationRule`: 分配规则(JSON格式或文本)
### 4.4 复制名额分配
**接口描述**: 从源批次复制名额分配到目标批次
#### 请求信息
```http
POST /jcbt/scholarshipQuota/copy?sourceBatchId=1&targetBatchId=2
Content-Type: application/json
Authorization: Bearer {token}
clientid: e5cd7e4891bf95d1d19206ce24a7b32e
```
#### 请求参数
```json
[1, 2, 3] // 要复制的奖学金类型ID列表
```
### 4.5 更新名额使用情况
**接口描述**: 更新名额的使用数量
#### 请求信息
```http
PUT /jcbt/scholarshipQuota/updateUsage/1?usedChange=1
Authorization: Bearer {token}
clientid: e5cd7e4891bf95d1d19206ce24a7b32e
```
#### 参数说明
- `id`: 名额分配ID
- `usedChange`: 使用数量变化(正数增加,负数减少)
---
## 🗑️ 5. 删除类接口
### 5.1 删除名额分配
**接口描述**: 删除指定的名额分配记录(支持批量删除)
#### 请求信息
```http
DELETE /jcbt/scholarshipQuota/1,2,3
Authorization: Bearer {token}
clientid: e5cd7e4891bf95d1d19206ce24a7b32e
```
#### 响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": null
}
```
---
## 📤 6. 导出类接口
### 6.1 导出名额分配
**接口描述**: 导出名额分配数据到Excel文件
#### 请求信息
```http
POST /jcbt/scholarshipQuota/export
Content-Type: application/json
Authorization: Bearer {token}
clientid: e5cd7e4891bf95d1d19206ce24a7b32e
```
#### 请求参数
```json
{
"batchId": 1, // 批次ID(可选)
"scholarshipTypeId": 1, // 奖学金类型ID(可选)
"allocationLevel": "COLLEGE" // 分配级别(可选)
}
```
---
## 🔍 7. 工具类接口
### 7.1 验证名额分配
**接口描述**: 验证名额分配数据的有效性
#### 请求信息
```http
POST /jcbt/scholarshipQuota/validate
Content-Type: application/json
Authorization: Bearer {token}
clientid: e5cd7e4891bf95d1d19206ce24a7b32e
```
#### 请求参数
```json
{
"batchId": 1,
"scholarshipTypeId": 1,
"allocationLevel": "COLLEGE",
"targetDeptId": 101,
"totalQuota": 10,
"usedQuota": 3,
"reservedQuota": 1
}
```
#### 响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": null // null表示验证通过,有错误信息则返回具体错误
}
```
---
## 📋 8. 数据字典
### 8.1 分配级别 (allocation_level)
- `UNIVERSITY`: 全校
- `COLLEGE`: 学院
- `MAJOR`: 专业
- `CLASS`: 班级
### 8.2 分配方式 (allocation_method)
- `MANUAL`: 手动分配
- `AUTO`: 自动分配
- `PROPORTIONAL`: 按比例分配
### 8.3 分配状态 (status)
- `ACTIVE`: 生效
- `INACTIVE`: 失效
- `PENDING`: 待审核
---
## ⚠️ 9. 错误处理
### 9.1 常见错误码
- `400`: 请求参数错误
- `401`: 未授权访问
- `403`: 权限不足
- `404`: 资源不存在
- `500`: 服务器内部错误
### 9.2 业务错误示例
```json
{
"code": 500,
"msg": "总名额必须大于0",
"data": null
}
```
```json
{
"code": 500,
"msg": "该批次和奖学金类型下已存在相同部门的名额分配",
"data": null
}
```
---
## 📝 10. 接口测试示例
### 10.1 测试环境
- 服务地址: `http://localhost:8080`
- 测试账号: admin/admin123
- 测试工具: Postman、ApiPost
### 10.2 完整测试流程
1. 登录获取Token
2. 查询评定批次列表
3. 创建名额分配
4. 查询名额分配列表
5. 修改名额分配
6. 执行名额调整
7. 查询使用统计
8. 导出数据
---
**文档维护人**: 开发团队
**最后更新**: 2025-01-27
**版本说明**: 首次创建,包含完整的17个API接口
@@ -0,0 +1,738 @@
# 奖学金申请管理API文档
**模块名称**: 奖学金申请管理
**版本**: v2.0
**创建日期**: 2025-01-01
**最后更新**: 2025-01-01
## 📋 目录
- [1. 概述](#1-概述)
- [2. 基础管理接口](#2-基础管理接口)
- [3. 业务功能接口](#3-业务功能接口)
- [4. 辅助功能接口](#4-辅助功能接口)
- [5. 数据模型](#5-数据模型)
- [6. 错误码说明](#6-错误码说明)
## 1. 概述
### 1.1 模块介绍
奖学金申请管理模块v2.0版本实现了从学生自主申请到班主任代申请的模式转换,支持班级名额分配、批量申请提交、审核流程等功能。
### 1.2 主要特性
- ✅ **班主任代申请**: 支持班主任为学生批量提交申请
- ✅ **名额控制**: 班级级别的名额分配和使用管理
- ✅ **时间窗口控制**: 支持申请时间窗口管理
- ✅ **审核流程**: 完整的申请审核和状态管理
- ✅ **材料管理**: 支持申请材料上传和审核
- ✅ **统计分析**: 提供详细的申请统计数据
### 1.3 权限说明
所有接口均需要Bearer Token认证,权限前缀:`jcbt:scholarshipApplication:`
### 1.4 接口基础信息
- **Base URL**: `/jcbt/scholarshipApplication`
- **Content-Type**: `application/json;charset=utf-8`
- **Authorization**: `Bearer {access_token}`
## 2. 基础管理接口
### 2.1 查询申请记录列表
**接口描述**: 分页查询奖学金申请记录列表
- **URL**: `GET /jcbt/scholarshipApplication/list`
- **权限**: `jcbt:scholarshipApplication:list`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| pageNum | Integer | 否 | 页码,默认1 |
| pageSize | Integer | 否 | 每页条数,默认10 |
| batchId | Long | 否 | 批次ID |
| scholarshipTypeId | Long | 否 | 奖学金类型ID |
| studentCode | String | 否 | 学生学号 |
| studentName | String | 否 | 学生姓名(模糊查询) |
| deptId | Long | 否 | 学院ID |
| classId | Long | 否 | 班级ID |
| applicantType | String | 否 | 申请人类型 |
| status | String | 否 | 申请状态 |
| beginCreateTime | String | 否 | 创建开始时间 |
| endCreateTime | String | 否 | 创建结束时间 |
**响应示例**:
```json
{
"total": 100,
"rows": [
{
"id": 1,
"batchId": 1,
"batchName": "2024-2025学年奖学金",
"scholarshipTypeId": 1,
"scholarshipTypeName": "国家奖学金",
"studentCode": "2021001001",
"studentName": "张三",
"studentId": 1001,
"deptId": 103,
"deptName": "计算机学院",
"classId": 1001,
"className": "计算机2021-1班",
"applicantType": "TEACHER",
"applicantId": 2001,
"applicantName": "李老师",
"applicationType": "RECOMMEND",
"comprehensiveScore": 95.5,
"academicScore": 96.0,
"moralScore": 95.0,
"physicalScore": 94.0,
"status": "SUBMITTED",
"submitTime": "2024-03-15 10:30:00",
"requireMaterials": 1,
"materialStatus": "PENDING",
"createTime": "2024-03-15 10:30:00"
}
],
"code": 200,
"msg": "查询成功"
}
```
### 2.2 获取申请记录详情
**接口描述**: 根据ID查询申请记录详细信息
- **URL**: `GET /jcbt/scholarshipApplication/{id}`
- **权限**: `jcbt:scholarshipApplication:query`
**路径参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| id | Long | 是 | 申请记录ID |
**响应示例**:
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"id": 1,
"batchId": 1,
"batchName": "2024-2025学年奖学金",
"scholarshipTypeId": 1,
"scholarshipTypeName": "国家奖学金",
"studentCode": "2021001001",
"studentName": "张三",
"studentId": 1001,
"deptId": 103,
"deptName": "计算机学院",
"classId": 1001,
"className": "计算机2021-1班",
"applicantType": "TEACHER",
"applicantId": 2001,
"applicantName": "李老师",
"applicationType": "RECOMMEND",
"applicationReason": "该学生综合成绩优秀,品学兼优",
"applicationDescription": "详细申请说明...",
"comprehensiveScore": 95.5,
"academicScore": 96.0,
"moralScore": 95.0,
"physicalScore": 94.0,
"aestheticScore": 93.0,
"laborScore": 94.0,
"awards": "国家级竞赛一等奖",
"socialPractice": "暑期社会实践活动",
"familyEconomicStatus": "家庭经济困难",
"status": "SUBMITTED",
"submitTime": "2024-03-15 10:30:00",
"requireMaterials": 1,
"materialStatus": "PENDING",
"createTime": "2024-03-15 10:30:00",
"updateTime": "2024-03-15 10:35:00"
}
}
```
### 2.3 新增申请记录
**接口描述**: 创建新的奖学金申请记录
- **URL**: `POST /jcbt/scholarshipApplication`
- **权限**: `jcbt:scholarshipApplication:add`
**请求体**:
```json
{
"batchId": 1,
"scholarshipTypeId": 1,
"studentCode": "2021001001",
"studentName": "张三",
"studentId": 1001,
"deptId": 103,
"deptName": "计算机学院",
"classId": 1001,
"className": "计算机2021-1班",
"applicantType": "TEACHER",
"applicantId": 2001,
"applicantName": "李老师",
"applicationType": "RECOMMEND",
"applicationReason": "该学生综合成绩优秀,品学兼优",
"applicationDescription": "详细申请说明...",
"comprehensiveScore": 95.5,
"academicScore": 96.0,
"moralScore": 95.0,
"physicalScore": 94.0,
"aestheticScore": 93.0,
"laborScore": 94.0,
"awards": "国家级竞赛一等奖",
"socialPractice": "暑期社会实践活动",
"familyEconomicStatus": "家庭经济困难",
"requireMaterials": 1,
"remark": "备注信息"
}
```
**响应示例**:
```json
{
"code": 200,
"msg": "操作成功",
"data": null
}
```
### 2.4 修改申请记录
**接口描述**: 修改申请记录信息
- **URL**: `PUT /jcbt/scholarshipApplication`
- **权限**: `jcbt:scholarshipApplication:edit`
**请求体**: 与新增接口相同,需包含id字段
### 2.5 删除申请记录
**接口描述**: 批量删除申请记录
- **URL**: `DELETE /jcbt/scholarshipApplication/{ids}`
- **权限**: `jcbt:scholarshipApplication:remove`
**路径参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| ids | String | 是 | 申请记录ID串,用逗号分隔 |
### 2.6 获取可申请奖学金类型
**接口描述**: 查询班级可申请的奖学金类型列表(有可用名额)
- **URL**: `GET /jcbt/scholarshipApplication/available`
- **权限**: `jcbt:scholarshipApplication:available`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| classId | Long | 是 | 班级ID |
| batchId | Long | 是 | 批次ID |
**响应示例**:
```json
{
"code": 200,
"msg": "查询成功",
"data": [
{
"scholarshipTypeId": 1,
"scholarshipTypeName": "国家奖学金",
"availableQuota": 2,
"totalQuota": 3
},
{
"scholarshipTypeId": 2,
"scholarshipTypeName": "国家励志奖学金",
"availableQuota": 5,
"totalQuota": 8
}
]
}
```
## 3. 业务功能接口
### 3.1 查询我的申请记录
**接口描述**: 查询班主任负责班级的申请记录
- **URL**: `GET /jcbt/scholarshipApplication/my`
- **权限**: `jcbt:scholarshipApplication:my`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| applicantId | Long | 是 | 申请人ID(班主任ID) |
| batchId | Long | 否 | 批次ID |
**响应示例**:
```json
{
"code": 200,
"msg": "查询成功",
"data": [
{
"id": 1,
"batchName": "2024-2025学年奖学金",
"scholarshipTypeName": "国家奖学金",
"studentCode": "2021001001",
"studentName": "张三",
"className": "计算机2021-1班",
"status": "SUBMITTED",
"submitTime": "2024-03-15 10:30:00"
}
]
}
```
### 3.2 查询待审核申请
**接口描述**: 查询待审核的申请记录列表
- **URL**: `GET /jcbt/scholarshipApplication/pending`
- **权限**: `jcbt:scholarshipApplication:pending`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| reviewerId | Long | 否 | 审核人ID |
| status | String | 否 | 申请状态 |
**响应示例**:
```json
{
"code": 200,
"msg": "查询成功",
"data": [
{
"id": 1,
"batchName": "2024-2025学年奖学金",
"scholarshipTypeName": "国家奖学金",
"studentCode": "2021001001",
"studentName": "张三",
"deptName": "计算机学院",
"className": "计算机2021-1班",
"status": "REVIEWING",
"submitTime": "2024-03-15 10:30:00",
"comprehensiveScore": 95.5
}
]
}
```
### 3.3 检查学生申请资格
**接口描述**: 检查学生是否符合申请条件
- **URL**: `GET /jcbt/scholarshipApplication/check`
- **权限**: `jcbt:scholarshipApplication:check`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| studentId | Long | 是 | 学生ID |
| batchId | Long | 是 | 批次ID |
| scholarshipTypeId | Long | 是 | 奖学金类型ID |
**响应示例**:
```json
{
"code": 200,
"msg": "查询成功",
"data": {
"eligible": true,
"message": "学生符合申请条件",
"restrictions": []
}
}
```
### 3.4 批量审核申请
**接口描述**: 批量审核申请记录
- **URL**: `POST /jcbt/scholarshipApplication/approve`
- **权限**: `jcbt:scholarshipApplication:approve`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| status | String | 是 | 审核状态(APPROVED/REJECTED) |
| reviewerId | Long | 是 | 审核人ID |
| reviewerName | String | 是 | 审核人姓名 |
| reviewComment | String | 否 | 审核意见 |
**请求体**:
```json
[1, 2, 3, 4]
```
**响应示例**:
```json
{
"code": 200,
"msg": "操作成功",
"data": null
}
```
## 4. 辅助功能接口
### 4.1 导出申请记录
**接口描述**: 导出申请记录列表为Excel文件
- **URL**: `POST /jcbt/scholarshipApplication/export`
- **权限**: `jcbt:scholarshipApplication:export`
**请求体**: 查询条件参数(与列表查询相同)
**响应**: Excel文件下载
### 4.2 导入申请记录
**接口描述**: 从Excel文件导入申请记录
- **URL**: `POST /jcbt/scholarshipApplication/import`
- **权限**: `jcbt:scholarshipApplication:import`
- **Content-Type**: `multipart/form-data`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| file | File | 是 | Excel文件 |
### 4.3 获取申请统计数据
**接口描述**: 获取申请相关的统计信息
- **URL**: `GET /jcbt/scholarshipApplication/statistics`
- **权限**: `jcbt:scholarshipApplication:statistics`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| batchId | Long | 否 | 批次ID |
| deptId | Long | 否 | 学院ID |
**响应示例**:
```json
{
"code": 200,
"msg": "查询成功",
"data": {
"statistics": [
{
"scholarshipTypeName": "国家奖学金",
"status": "SUBMITTED",
"count": 25,
"deptName": "计算机学院"
},
{
"scholarshipTypeName": "国家励志奖学金",
"status": "APPROVED",
"count": 15,
"deptName": "计算机学院"
}
],
"total": 40
}
}
```
### 4.4 班主任批量申请提交
**接口描述**: 班主任为学生批量提交申请(v2.0核心功能)
- **URL**: `POST /jcbt/scholarshipApplication/batch`
- **权限**: `jcbt:scholarshipApplication:batch`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| batchId | Long | 是 | 批次ID |
| scholarshipTypeId | Long | 是 | 奖学金类型ID |
| classId | Long | 是 | 班级ID |
**请求体**:
```json
[
{
"studentCode": "2021001001",
"studentName": "张三",
"studentId": 1001,
"deptId": 103,
"deptName": "计算机学院",
"className": "计算机2021-1班",
"applicantId": 2001,
"applicantName": "李老师",
"applicationType": "RECOMMEND",
"applicationReason": "综合成绩优秀",
"comprehensiveScore": 95.5,
"academicScore": 96.0,
"moralScore": 95.0,
"physicalScore": 94.0,
"aestheticScore": 93.0,
"laborScore": 94.0
},
{
"studentCode": "2021001002",
"studentName": "李四",
"studentId": 1002,
"deptId": 103,
"deptName": "计算机学院",
"className": "计算机2021-1班",
"applicantId": 2001,
"applicantName": "李老师",
"applicationType": "RECOMMEND",
"applicationReason": "学习态度端正",
"comprehensiveScore": 92.0,
"academicScore": 93.0,
"moralScore": 91.0,
"physicalScore": 92.0,
"aestheticScore": 90.0,
"laborScore": 93.0
}
]
```
**响应示例**:
```json
{
"code": 200,
"msg": "操作成功",
"data": null
}
```
### 4.5 提交申请
**接口描述**: 将草稿状态的申请提交审核
- **URL**: `POST /jcbt/scholarshipApplication/{id}/submit`
- **权限**: `jcbt:scholarshipApplication:submit`
**路径参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| id | Long | 是 | 申请记录ID |
### 4.6 撤回申请
**接口描述**: 撤回已提交的申请
- **URL**: `POST /jcbt/scholarshipApplication/{id}/withdraw`
- **权限**: `jcbt:scholarshipApplication:withdraw`
**路径参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| id | Long | 是 | 申请记录ID |
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| reason | String | 否 | 撤回原因 |
### 4.7 获取班级名额使用情况
**接口描述**: 查询班级的名额分配和使用情况
- **URL**: `GET /jcbt/scholarshipApplication/quota`
- **权限**: `jcbt:scholarshipApplication:quota`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| classId | Long | 是 | 班级ID |
| batchId | Long | 是 | 批次ID |
**响应示例**:
```json
{
"code": 200,
"msg": "查询成功",
"data": {
"quotas": [
{
"scholarshipTypeId": 1,
"scholarshipTypeName": "国家奖学金",
"totalQuota": 3,
"usedQuota": 1,
"availableQuota": 2,
"status": "ACTIVE"
},
{
"scholarshipTypeId": 2,
"scholarshipTypeName": "国家励志奖学金",
"totalQuota": 8,
"usedQuota": 3,
"availableQuota": 5,
"status": "ACTIVE"
}
],
"totalQuota": 11,
"usedQuota": 4,
"availableQuota": 7
}
}
```
## 5. 数据模型
### 5.1 申请状态枚举
| 状态值 | 说明 | 描述 |
|--------|------|------|
| DRAFT | 草稿 | 申请记录已创建但未提交 |
| SUBMITTED | 已提交 | 申请已提交,等待审核 |
| REVIEWING | 审核中 | 申请正在审核过程中 |
| APPROVED | 已通过 | 申请审核通过 |
| REJECTED | 已拒绝 | 申请审核被拒绝 |
| WITHDRAWN | 已撤回 | 申请人主动撤回申请 |
### 5.2 申请人类型枚举
| 类型值 | 说明 | 描述 |
|--------|------|------|
| STUDENT | 学生申请 | 学生自主申请(v1.0模式) |
| TEACHER | 教师代申请 | 班主任代学生申请(v2.0模式) |
### 5.3 申请类型枚举
| 类型值 | 说明 | 描述 |
|--------|------|------|
| RECOMMEND | 教师推荐 | 班主任推荐学生申请 |
| AUTO | 自动评定 | 系统根据成绩自动评定 |
| DIRECT | 直接指定 | 学院直接指定学生 |
### 5.4 材料状态枚举
| 状态值 | 说明 | 描述 |
|--------|------|------|
| PENDING | 待上传 | 材料尚未上传 |
| PARTIAL | 部分上传 | 部分材料已上传 |
| COMPLETE | 完整上传 | 所有材料已上传完整 |
## 6. 错误码说明
### 6.1 通用错误码
| 错误码 | 说明 | 解决方案 |
|--------|------|----------|
| 400 | 请求参数错误 | 检查请求参数格式和必填项 |
| 401 | 认证失败 | 检查Token是否有效 |
| 403 | 权限不足 | 联系管理员分配相应权限 |
| 404 | 资源不存在 | 检查资源ID是否正确 |
| 500 | 服务器内部错误 | 联系技术支持 |
### 6.2 业务错误码
| 错误信息 | 说明 | 解决方案 |
|----------|------|----------|
| "该学生在此批次中已有申请记录" | 学生重复申请 | 检查申请记录,避免重复提交 |
| "班级可用名额不足" | 名额不够 | 等待名额释放或调整名额分配 |
| "只有草稿状态的申请才能提交" | 状态错误 | 检查申请状态 |
| "已审核的申请不能撤回" | 撤回限制 | 已审核申请无法撤回 |
| "申请时间窗口未开放" | 时间限制 | 等待申请时间窗口开放 |
## 7. 使用示例
### 7.1 班主任批量申请流程
```javascript
// 1. 查询可申请的奖学金类型
const availableTypes = await fetch('/jcbt/scholarshipApplication/available?classId=1001&batchId=1', {
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/json'
}
});
// 2. 检查班级名额使用情况
const quotaUsage = await fetch('/jcbt/scholarshipApplication/quota?classId=1001&batchId=1', {
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/json'
}
});
// 3. 批量提交申请
const batchSubmit = await fetch('/jcbt/scholarshipApplication/batch?batchId=1&scholarshipTypeId=1&classId=1001', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/json'
},
body: JSON.stringify([
{
"studentCode": "2021001001",
"studentName": "张三",
"studentId": 1001,
"deptId": 103,
"deptName": "计算机学院",
"className": "计算机2021-1班",
"applicantId": 2001,
"applicantName": "李老师",
"applicationType": "RECOMMEND",
"applicationReason": "综合成绩优秀",
"comprehensiveScore": 95.5,
"academicScore": 96.0
}
])
});
```
### 7.2 审核申请流程
```javascript
// 1. 查询待审核申请
const pendingApplications = await fetch('/jcbt/scholarshipApplication/pending?status=SUBMITTED', {
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/json'
}
});
// 2. 批量审核
const batchApprove = await fetch('/jcbt/scholarshipApplication/approve?status=APPROVED&reviewerId=3001&reviewerName=王老师&reviewComment=审核通过', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/json'
},
body: JSON.stringify([1, 2, 3])
});
```
---
**文档维护**: 技术团队
**联系方式**: tech@example.com
**最后更新**: 2025-01-01
@@ -0,0 +1,200 @@
# SQL调试日志使用说明 - 班级名额查询问题排查
**创建时间**: 2025-01-27
**目的**: 帮助排查班主任批量申请奖学金页面中班级名额和全校名额查询的问题
## 🎯 功能说明
为了帮助您验证班级名额和全校名额查询的SQL语句执行情况,我们增加了以下功能:
### 1. **详细的业务日志**
- 在 `getScholarshipTypesWithQuota` 方法中增加了详细的日志输出
- 记录每一步的执行过程和查询结果
- 包含SQL参数和查询结果的详细信息
### 2. **MyBatis SQL日志**
- 配置了MyBatis的SQL日志输出
- 可以看到实际执行的SQL语句和参数绑定
- 包含查询结果和执行时间
### 3. **专用调试接口**
- 提供了专门的调试API接口
- 可以单独测试班级名额查询和全校名额查询
- 返回详细的调试信息
## 🔧 配置说明
### 已添加的配置项
在 `backend/ruoyi-admin/src/main/resources/application-dev.yml` 中添加了:
```yaml
# SQL日志配置(用于调试班级名额查询问题)
logging:
level:
# 开启 MyBatis SQL 日志
org.dromara.jcbt.mapper: DEBUG
org.dromara.jcbt.service: DEBUG
# 开启 MyBatis-Plus SQL 日志
com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor: DEBUG
# 开启 HikariCP 连接池日志(可选)
com.zaxxer.hikari: DEBUG
# 开启 P6Spy SQL 日志(更详细的SQL执行日志)
p6spy: INFO
# MyBatis 配置
mybatis-plus:
configuration:
# 开启 SQL 日志打印
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 开启驼峰命名转换
map-underscore-to-camel-case: true
```
## 📋 使用方法
### 方法一:调用现有接口观察日志
1. **启动后端服务**
```bash
cd backend
./start-main.sh
```
2. **调用接口**
```http
GET http://localhost:8080/jcbt/scholarshipApplication/scholarshipTypesWithQuota?batchId=1&classId=123
```
3. **观察控制台日志输出**
- 查看详细的业务流程日志
- 查看MyBatis执行的SQL语句
- 查看查询结果和处理过程
### 方法二:使用专用调试接口
#### 1. 完整流程测试
```http
GET http://localhost:8080/jcbt/scholarshipApplication/debug/sqlLogs?batchId=1&classId=123
```
#### 2. 单个奖学金类型测试
```http
GET http://localhost:8080/jcbt/scholarshipApplication/debug/sqlLogs?batchId=1&classId=123&scholarshipTypeId=1
```
## 📊 日志输出示例
### 业务日志示例
```
2025-01-27 16:20:00.123 INFO --- [http-nio-8080-exec-1] o.d.j.s.i.JcbtScholarshipApplicationServiceImpl : === 开始获取带名额信息的奖学金类型 ===
2025-01-27 16:20:00.124 INFO --- [http-nio-8080-exec-1] o.d.j.s.i.JcbtScholarshipApplicationServiceImpl : 输入参数 - 批次ID: 1, 班级ID: 123
2025-01-27 16:20:00.125 INFO --- [http-nio-8080-exec-1] o.d.j.s.i.JcbtScholarshipApplicationServiceImpl : --- 处理奖学金类型ID: 1 ---
2025-01-27 16:20:00.126 INFO --- [http-nio-8080-exec-1] o.d.j.s.i.JcbtScholarshipApplicationServiceImpl : 开始查询班级名额 - SQL参数: classId=123, scholarshipTypeId=1, batchId=1
2025-01-27 16:20:00.127 INFO --- [http-nio-8080-exec-1] o.d.j.s.i.JcbtScholarshipApplicationServiceImpl : 执行SQL: SELECT * FROM jcbt_scholarship_class_quota WHERE class_id = 123 AND scholarship_type_id = 1 AND batch_id = 1 AND status = '1' AND deleted = 0
```
### MyBatis SQL日志示例
```
2025-01-27 16:20:00.128 DEBUG --- [http-nio-8080-exec-1] o.d.j.m.JcbtScholarshipClassQuotaMapper.selectAvailableQuota : ==> Preparing: select id, batch_id, scholarship_type_id, dept_id, class_id, total_quota, used_quota, available_quota, status, remark, create_by, create_time, update_by, update_time from jcbt_scholarship_class_quota where class_id = ? and scholarship_type_id = ? and batch_id = ? and status = '1' and deleted = 0
2025-01-27 16:20:00.129 DEBUG --- [http-nio-8080-exec-1] o.d.j.m.JcbtScholarshipClassQuotaMapper.selectAvailableQuota : ==> Parameters: 123(Long), 1(Long), 1(Long)
2025-01-27 16:20:00.135 DEBUG --- [http-nio-8080-exec-1] o.d.j.m.JcbtScholarshipClassQuotaMapper.selectAvailableQuota : <== Total: 1
```
## 🔍 问题排查指南
### 1. 班级名额查询问题
**如果查询结果为空,可能的原因:**
1. **数据不存在**
- 检查 `jcbt_scholarship_class_quota` 表中是否有对应记录
- 确认 `class_id`, `scholarship_type_id`, `batch_id` 参数值正确
2. **状态问题**
- 检查记录的 `status` 字段是否为 '1'(启用状态)
- 检查记录的 `deleted` 字段是否为 0(未删除)
3. **权限问题**
- 确认当前用户有查询权限
- 检查多租户配置是否正确
### 2. 全校名额查询问题
**如果查询结果为空,可能的原因:**
1. **数据不存在**
- 检查 `jcbt_scholarship_quota` 表中是否有对应记录
- 确认 `batch_id`, `scholarship_type_id` 参数值正确
2. **关联表问题**
- 检查与 `jcbt_scholarship_batch` 表的关联
- 检查与 `jcbt_scholarship_type` 表的关联
- 检查与 `sys_dept` 表的关联
### 3. 性能问题
**如果查询速度慢:**
1. **索引检查**
```sql
-- 检查班级名额表的索引
SHOW INDEX FROM jcbt_scholarship_class_quota;
-- 检查全校名额表的索引
SHOW INDEX FROM jcbt_scholarship_quota;
```
2. **建议添加的索引**
```sql
-- 班级名额表复合索引
CREATE INDEX idx_class_quota_query ON jcbt_scholarship_class_quota(class_id, scholarship_type_id, batch_id, status, deleted);
-- 全校名额表复合索引
CREATE INDEX idx_school_quota_query ON jcbt_scholarship_quota(batch_id, scholarship_type_id, deleted);
```
## 🚨 注意事项
### 1. **生产环境使用**
- 这些调试配置仅适用于开发和测试环境
- 生产环境请关闭详细的SQL日志,避免性能影响
- 可以将日志级别调整为 WARN 或 ERROR
### 2. **日志文件大小**
- SQL日志会产生大量输出,注意日志文件大小
- 建议配置日志轮转和清理策略
### 3. **敏感信息**
- 注意日志中可能包含敏感的业务数据
- 生产环境需要对日志进行脱敏处理
## 📞 使用步骤总结
1. **确保配置生效**:重启后端服务
2. **调用调试接口**:使用提供的调试API
3. **观察日志输出**:查看控制台的详细日志
4. **分析问题原因**:根据日志信息排查问题
5. **验证修复效果**:修复后重新测试
## 🔧 临时关闭调试日志
如果需要临时关闭调试日志,可以修改配置:
```yaml
logging:
level:
org.dromara.jcbt.mapper: INFO
org.dromara.jcbt.service: INFO
mybatis-plus:
configuration:
# 关闭 SQL 日志打印
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
```
---
**创建者**: Cursor AI Assistant
**更新时间**: 2025-01-27 16:30:00
**状态**: 已配置完成,可直接使用
@@ -0,0 +1,316 @@
# 前后端接口一致性规范
> **文档创建时间**: 2025-01-16
> **适用项目**: 校园管理系统 (hzdyjs_xg)
> **目标**: 彻底杜绝前后端字段名不一致等接口问题
## 🎯 规范目标
- **零容忍**前后端字段名不一致
- **统一化**接口定义和文档管理
- **自动化**一致性检查和验证
- **标准化**开发流程和协作机制
---
## 📋 核心规范标准
### 1. 字段命名统一原则
#### 🔴 强制性规范
```markdown
✅ 前后端字段名必须**完全一致**(大小写、拼写)
✅ 使用**驼峰命名法** (camelCase)
✅ 后端Entity/Bo/Vo**统一字段名**
✅ 前端TypeScript接口**严格对应**后端模型
```
#### 📝 标准字段名对照表
| 中文含义 | 标准字段名 | 错误示例 | 说明 |
|---------|-----------|---------|-----|
| 学生学号 | `studentNo` | ~~studentCode~~ | 统一使用No结尾 |
| 学生姓名 | `studentName` | ~~name~~ | 明确实体前缀 |
| 创建时间 | `createTime` | ~~createdTime~~ | 与RuoYi框架保持一致 |
| 当前状态 | `currentStatus` | ~~status~~ | 明确状态含义 |
### 2. 接口定义同步机制
#### 🔄 开发流程(必须遵循)
```mermaid
graph LR
A[后端模型定义] --> B[生成API文档]
B --> C[前端接口定义]
C --> D[一致性验证]
D --> E[代码审查]
E --> F[集成测试]
```
#### 📚 文档同步要求
- **后端模型变更** → **立即更新API文档**
- **API文档更新** → **立即通知前端团队**
- **前端接口定义** → **必须基于最新API文档**
---
## 🔧 技术实现方案
### 1. TypeScript接口自动生成
#### 方案A: 基于Swagger自动生成
```bash
# 安装swagger-typescript-api
npm install -D swagger-typescript-api
# 自动生成TypeScript接口
npx swagger-typescript-api -p http://localhost:8080/v3/api-docs -o ./src/api/types -n api-types.ts
```
#### 方案B: 后端注解驱动生成
```java
// 后端使用详细注解
@ApiModel(description = "奖学金申请记录")
public class JcbtScholarshipApplicationVo {
@ApiModelProperty(value = "学生学号", required = true)
private String studentNo; // 标准字段名
}
```
### 2. 一致性检查脚本
#### 检查脚本示例 (`scripts/check-api-consistency.js`)
```javascript
// 检查前后端字段名一致性
const fs = require('fs');
const path = require('path');
function checkApiConsistency() {
// 读取Swagger文档
const swaggerDoc = require('../docs/swagger.json');
// 读取前端TypeScript接口
const frontendTypes = fs.readFileSync('./src/api/types.ts', 'utf8');
// 字段名一致性检查
const inconsistencies = [];
Object.keys(swaggerDoc.definitions).forEach(model => {
const backendFields = Object.keys(swaggerDoc.definitions[model].properties);
const frontendInterface = extractInterfaceFields(frontendTypes, model);
backendFields.forEach(field => {
if (!frontendInterface.includes(field)) {
inconsistencies.push({
model: model,
field: field,
issue: 'Backend field missing in frontend'
});
}
});
});
if (inconsistencies.length > 0) {
console.error('❌ API一致性检查失败:', inconsistencies);
process.exit(1);
} else {
console.log('✅ API一致性检查通过');
}
}
checkApiConsistency();
```
### 3. Git Pre-commit Hook
#### `.husky/pre-commit` 配置
```bash
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
# 运行一致性检查
npm run check:api-consistency
# ESLint检查
npm run lint
# 类型检查
npm run type-check
```
---
## 📋 Code Review检查清单
### 🔍 前后端接口变更必查项
#### ✅ 后端变更检查
- [ ] Entity/Bo/Vo字段名是否一致?
- [ ] 新增字段是否有JSR303校验注解?
- [ ] 是否更新了对应的API文档?
- [ ] 是否通知了前端团队?
#### ✅ 前端变更检查
- [ ] TypeScript接口是否与后端模型一致?
- [ ] 新增字段是否有对应的校验规则?
- [ ] 是否测试了完整的数据流转?
- [ ] 是否处理了字段为空的情况?
#### ✅ API文档检查
- [ ] 字段类型是否准确描述?
- [ ] 必填字段是否明确标注?
- [ ] 示例数据是否真实有效?
- [ ] 变更记录是否完整记录?
---
## 🧪 测试验证机制
### 1. 接口契约测试
#### Postman集合测试
```json
{
"name": "奖学金申请API测试",
"tests": [
{
"name": "字段完整性检查",
"script": "pm.test('Response has all required fields', function () {
const response = pm.response.json();
pm.expect(response.data).to.have.property('studentNo');
pm.expect(response.data).to.have.property('studentName');
pm.expect(response.data).to.have.property('currentStatus');
});"
}
]
}
```
### 2. 自动化集成测试
#### Jest测试用例
```typescript
describe('ScholarshipApplication API', () => {
test('should have consistent field names', async () => {
const response = await getScholarshipApplication(1);
// 检查关键字段是否存在
expect(response.data).toHaveProperty('studentNo');
expect(response.data).not.toHaveProperty('studentCode'); // 确保错误字段不存在
expect(response.data).toHaveProperty('currentStatus');
});
});
```
---
## 📊 监控和度量
### 1. 错误监控指标
#### 关键监控点
- **接口调用失败率** - 字段缺失导致的400错误
- **前端TypeError数量** - undefined字段访问错误
- **Code Review拒绝率** - 接口不一致相关的PR被拒绝次数
### 2. 质量度量标准
#### 🎯 目标指标
- **零字段名不一致**事故
- **API文档准确率** > 99%
- **接口契约测试覆盖率** > 90%
- **一致性检查自动化率** = 100%
---
## 🚨 应急处理流程
### 发现不一致问题时的处理步骤
#### 1. 立即响应 (10分钟内)
```bash
# 1. 确认影响范围
git log --oneline --grep="studentCode\|studentNo" -n 10
# 2. 创建紧急修复分支
git checkout -b hotfix/field-consistency-fix
# 3. 快速定位所有不一致点
grep -r "studentCode" web/src/
```
#### 2. 快速修复 (30分钟内)
- 统一修改为标准字段名
- 更新相关TypeScript接口
- 执行一致性检查脚本
- 提交带有详细说明的commit
#### 3. 验证和部署 (60分钟内)
- 执行完整的接口测试
- Code Review快速通道
- 生产环境热修复部署
- 监控系统错误日志
#### 4. 复盘和改进 (24小时内)
- 记录问题根因分析
- 更新预防措施
- 加强相关流程和检查
---
## 🎓 培训和知识传递
### 1. 团队培训计划
#### 📚 培训内容
- **接口设计最佳实践**
- **前后端协作规范**
- **一致性检查工具使用**
- **问题排查和修复流程**
### 2. 文档和资料
#### 🔗 参考资料
- [RESTful API设计规范](./RESTful-API设计规范.md)
- [TypeScript接口定义标准](./TypeScript接口定义标准.md)
- [前后端协作流程](./前后端协作流程.md)
- [常见问题FAQ](./前后端接口FAQ.md)
---
## 📈 持续改进
### 季度审查机制
- **接口质量回顾** - 每季度统计不一致问题
- **工具链优化** - 评估和改进自动化工具
- **流程迭代** - 基于实际问题优化流程
- **培训效果评估** - 团队技能提升评估
### 长期规划
- **接口代码生成自动化**
- **实时一致性监控系统**
- **AI辅助接口设计**
- **跨项目规范标准化**
---
## ⚡ 快速参考
### 常用命令
```bash
# 检查字段名一致性
npm run check:api-consistency
# 生成TypeScript接口
npm run generate:api-types
# 运行接口契约测试
npm run test:api-contract
```
### 应急联系人
- **前端负责人**: 技术负责人
- **后端负责人**: 技术负责人
- **DevOps负责人**: 运维负责人
---
**📝 文档维护**: 本规范文档随项目发展持续更新,每月审查一次,确保实用性和时效性。