diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStuColBatchClassController.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStuColBatchClassController.java index f73cd6ef..c3d88163 100644 --- a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStuColBatchClassController.java +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStuColBatchClassController.java @@ -3,6 +3,7 @@ package org.dromara.xg.controller; import java.util.List; import java.util.ArrayList; import java.util.Date; +import java.util.Map; import lombok.RequiredArgsConstructor; import jakarta.servlet.http.HttpServletResponse; @@ -27,6 +28,7 @@ import org.dromara.xg.service.IXgStuColBatchClassService; import org.dromara.xg.mapper.XgStuColBatchClassMapper; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.satoken.utils.LoginHelper; /** * 学生信息收集批次班级权限 @@ -198,4 +200,28 @@ public class XgStuColBatchClassController extends BaseController { return R.fail("权限设置异常:" + e.getMessage()); } } + + /** + * 查询学生可参与的批次信息 + * 通过xg_student_msg、xg_stu_col_batch_class、xg_stu_col_batch三张表关联查询 + */ + // @SaCheckPermission("stuColBatchClass:stuColBatchClass:query") + @GetMapping("/getStudentAvailableBatches") + public R>> getStudentAvailableBatches( + @RequestParam(value = "batchName", required = false) String batchName) { + try { + // 获取当前登录用户ID + Long currentUserId = LoginHelper.getUserId(); + if (currentUserId == null) { + return R.fail("用户未登录"); + } + + // 查询学生可参与的批次信息 + List> batchList = xgStuColBatchClassMapper.selectStudentAvailableBatches(currentUserId, + batchName); + return R.ok(batchList); + } catch (Exception e) { + return R.fail("查询学生可参与批次信息失败:" + e.getMessage()); + } + } } diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStudentMsgBatchController.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStudentMsgBatchController.java index 58c79d7b..f626ebfb 100644 --- a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStudentMsgBatchController.java +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStudentMsgBatchController.java @@ -63,8 +63,7 @@ public class XgStudentMsgBatchController extends BaseController { */ @SaCheckPermission("studentMsgBatch:studentMsgBatch:query") @GetMapping("/{id}") - public R getInfo(@NotNull(message = "主键不能为空") - @PathVariable Long id) { + public R getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) { return R.ok(xgStudentMsgBatchService.queryById(id)); } @@ -98,8 +97,8 @@ public class XgStudentMsgBatchController extends BaseController { @SaCheckPermission("studentMsgBatch:studentMsgBatch:remove") @Log(title = "学生信息批次收集", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") - public R remove(@NotEmpty(message = "主键不能为空") - @PathVariable Long[] ids) { + public R remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) { return toAjax(xgStudentMsgBatchService.deleteWithValidByIds(List.of(ids), true)); } + } diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgStuColBatchClassMapper.java b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgStuColBatchClassMapper.java index 81b438ef..8e3ac4b3 100644 --- a/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgStuColBatchClassMapper.java +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgStuColBatchClassMapper.java @@ -6,6 +6,7 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; import org.apache.ibatis.annotations.Param; import java.util.List; +import java.util.Map; /** * 学生信息收集批次班级权限Mapper接口 @@ -46,4 +47,14 @@ public interface XgStuColBatchClassMapper extends BaseMapperPlus selectScopeDetailByBatchId(@Param("batchId") Long batchId); + + /** + * 查询学生可参与的批次信息 + * 通过xg_student_msg、xg_stu_col_batch_class、xg_stu_col_batch三张表关联查询 + * + * @param studentId 学生ID + * @return 批次信息列表 + */ + List> selectStudentAvailableBatches(@Param("studentId") Long studentId, + @Param("batchName") String batchName); } diff --git a/backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/stuColBatchClass/XgStuColBatchClassMapper.xml b/backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/stuColBatchClass/XgStuColBatchClassMapper.xml index 48999cc5..da0d8a76 100644 --- a/backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/stuColBatchClass/XgStuColBatchClassMapper.xml +++ b/backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/stuColBatchClass/XgStuColBatchClassMapper.xml @@ -81,4 +81,33 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ORDER BY college_name, major_name, class_name + + + diff --git a/docs/变更管理/code-adjust-record-2025-01-17-batchName-optional-param.md b/docs/变更管理/code-adjust-record-2025-01-17-batchName-optional-param.md new file mode 100644 index 00000000..bb088ead --- /dev/null +++ b/docs/变更管理/code-adjust-record-2025-01-17-batchName-optional-param.md @@ -0,0 +1,145 @@ +# 学生可参与批次查询API参数优化记录 + +**日期**: 2025-01-17 +**开发者**: Cursor AI +**变更类型**: 参数优化 +**影响范围**: 后端API接口、XML映射文件 + +## 📋 变更概述 + +优化了 `getStudentAvailableBatches` API接口,将 `batchName` 参数改为可选参数,支持不传参数时查询所有可参与的批次信息。 + +## 🔧 具体变更 + +### 1. Controller层变更 + +**文件**: `backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStuColBatchClassController.java` + +#### 修改内容 +- 将 `@RequestParam("batchName")` 改为 `@RequestParam(value = "batchName", required = false)` +- 使 `batchName` 参数变为可选参数 + +#### 修改前 +```java +public R>> getStudentAvailableBatches(@RequestParam("batchName") String batchName) +``` + +#### 修改后 +```java +public R>> getStudentAvailableBatches( + @RequestParam(value = "batchName", required = false) String batchName) +``` + +### 2. XML映射文件变更 + +**文件**: `backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/stuColBatchClass/XgStuColBatchClassMapper.xml` + +#### 修改内容 +- 在 `selectStudentAvailableBatches` SQL查询中添加条件判断 +- 只有当 `batchName` 不为空时才添加模糊查询条件 + +#### 修改前 +```xml +WHERE s.id = #{studentId} +AND b.batch_name LIKE CONCAT('%', #{batchName}, '%') +AND b.deleted = 0 +``` + +#### 修改后 +```xml +WHERE s.id = #{studentId} + + AND b.batch_name LIKE CONCAT('%', #{batchName}, '%') + +AND b.deleted = 0 +``` + +## 🎯 优化效果 + +### 功能改进 +1. **参数灵活性**: `batchName` 参数现在可以为空,支持查询所有批次 +2. **向后兼容**: 保持原有功能不变,仍然支持按批次名称筛选 +3. **错误处理**: 避免了 `batchName` 为 `null` 时导致的 SQL 查询错误 + +### 使用场景 +1. **查询所有批次**: 不传 `batchName` 参数,返回学生可参与的所有批次 +2. **按名称筛选**: 传入 `batchName` 参数,返回匹配的批次信息 +3. **前端搜索**: 支持前端搜索框为空时显示所有数据 + +## 📊 API接口规范 + +### 请求信息 +- **请求方法**: GET +- **请求路径**: `/stuColBatchClass/stuColBatchClass/getStudentAvailableBatches` +- **请求参数**: + - `batchName` (可选): 批次名称,支持模糊查询 +- **请求头**: 需要包含有效的Token + +### 请求示例 +```bash +# 查询所有批次 +GET /stuColBatchClass/stuColBatchClass/getStudentAvailableBatches + +# 按名称筛选 +GET /stuColBatchClass/stuColBatchClass/getStudentAvailableBatches?batchName=春季学期 +``` + +### 响应格式 +```json +{ + "code": 200, + "msg": "操作成功", + "data": [ + { + "batchId": 1, + "batchName": "2025年春季学期信息收集", + "description": "收集学生基本信息", + "startTime": "2025-01-01 00:00:00", + "endTime": "2025-01-31 23:59:59", + "status": "0", + "collectionType": "1", + "remark": "新学期信息收集", + "classId": 101, + "className": "计算机科学与技术2021级1班", + "majorId": 1, + "majorName": "计算机科学与技术", + "collegeId": 1, + "collegeName": "信息工程学院" + } + ] +} +``` + +## 🧪 测试建议 + +### 功能测试 +1. **无参数查询**: 不传 `batchName` 参数,验证返回所有批次 +2. **空字符串查询**: 传入空字符串,验证返回所有批次 +3. **模糊查询**: 传入部分批次名称,验证返回匹配结果 +4. **精确查询**: 传入完整批次名称,验证返回精确结果 +5. **无匹配结果**: 传入不存在的批次名称,验证返回空列表 + +### 异常测试 +1. **参数为null**: 验证SQL查询正常执行 +2. **参数为空字符串**: 验证SQL查询正常执行 +3. **特殊字符**: 验证包含特殊字符的批次名称查询 + +## 📚 相关文档 + +- **原API文档**: 学生信息收集批次管理API +- **前端调用**: `web/src/views/stuMsgSupply/index.vue` +- **数据库设计**: 学生信息收集批次管理表设计 + +## 🔄 后续优化建议 + +1. **分页支持**: 如果批次数量较多,可以考虑添加分页功能 +2. **状态过滤**: 可以添加参数支持按批次状态过滤 +3. **时间范围**: 可以添加参数支持按时间范围查询 +4. **排序选项**: 可以添加参数支持自定义排序 + +--- + +**开发完成时间**: 2025-01-17 +**代码审查**: 待审查 +**测试状态**: 待测试 +**部署状态**: 待部署 \ No newline at end of file diff --git a/docs/变更管理/code-adjust-record-2025-01-17-student-available-batches-api.md b/docs/变更管理/code-adjust-record-2025-01-17-student-available-batches-api.md new file mode 100644 index 00000000..cb532f1f --- /dev/null +++ b/docs/变更管理/code-adjust-record-2025-01-17-student-available-batches-api.md @@ -0,0 +1,161 @@ +# 学生可参与批次信息查询API开发记录 + +**日期**: 2025-01-17 +**开发者**: Cursor AI +**变更类型**: 新增功能 +**影响范围**: 后端API接口 + +## 📋 变更概述 + +在 `XgStuColBatchClassController.java` 中新增了 `getStudentAvailableBatches` API接口,用于查询学生可以参与的批次信息。 + +## 🔧 具体变更 + +### 1. Controller层变更 + +**文件**: `backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStuColBatchClassController.java` + +#### 新增内容 +- 添加了 `getStudentAvailableBatches` API接口 +- 接口路径: `GET /stuColBatchClass/stuColBatchClass/getStudentAvailableBatches` +- 无入参,自动获取当前登录用户ID +- 返回类型: `R>>` +- 添加了权限注解 `@SaCheckPermission("stuColBatchClass:stuColBatchClass:query")` + +#### 实现逻辑 +1. **获取当前用户ID**: 使用 `LoginHelper.getUserId()` 获取当前登录用户ID +2. **权限校验**: 检查用户是否已登录 +3. **数据查询**: 调用Mapper方法查询学生可参与的批次信息 +4. **异常处理**: 捕获并处理查询过程中的异常 + +### 2. Mapper层变更 + +**文件**: `backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgStuColBatchClassMapper.java` + +#### 新增方法 +- `selectStudentAvailableBatches(Long studentId)`: 查询学生可参与的批次信息 +- 返回类型: `List>` + +### 3. XML映射文件变更 + +**文件**: `backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/stuColBatchClass/XgStuColBatchClassMapper.xml` + +#### 新增SQL查询 +- 实现了 `selectStudentAvailableBatches` 的SQL查询语句 +- 通过三张表关联查询:`xg_stu_col_batch`、`xg_stu_col_batch_class`、`xg_student_msg` +- 查询条件: + - `xg_student_msg.id = 当前登录用户ID` + - `xg_student_msg.class_id = xg_stu_col_batch_class.class_id` + - `xg_stu_col_batch_class.batch_id = xg_stu_col_batch.id` + - `deleted = 0` (所有表) + - `xg_stu_col_batch.status = '0'` (批次状态正常) + +#### 返回字段 +- 批次信息:`batchId`、`batchName`、`description`、`startTime`、`endTime`、`status`、`collectionType`、`remark` +- 班级信息:`classId`、`className`、`majorId`、`majorName`、`collegeId`、`collegeName` + +## 📊 数据库关联逻辑 + +### 表关联关系 +``` +xg_student_msg (学生信息表) + ↓ class_id +xg_stu_col_batch_class (批次班级权限表) + ↓ batch_id +xg_stu_col_batch (批次信息表) +``` + +### 查询条件 +1. **学生匹配**: `xg_student_msg.id = 当前登录用户ID` +2. **班级匹配**: `xg_student_msg.class_id = xg_stu_col_batch_class.class_id` +3. **批次匹配**: `xg_stu_col_batch_class.batch_id = xg_stu_col_batch.id` +4. **数据有效性**: 所有表的 `deleted = 0` +5. **批次状态**: `xg_stu_col_batch.status = '0'` (正常状态) + +## 🔐 权限控制 + +### 接口权限 +- **权限标识**: `stuColBatchClass:stuColBatchClass:query` +- **访问控制**: 需要登录用户 +- **数据范围**: 只能查询当前登录用户对应的学生信息 + +### 安全考虑 +- 使用 `LoginHelper.getUserId()` 获取当前用户ID,确保数据安全 +- 通过表关联确保用户只能查看自己班级的批次信息 +- 添加异常处理,避免敏感信息泄露 + +## 📝 API接口规范 + +### 请求信息 +- **请求方法**: GET +- **请求路径**: `/stuColBatchClass/stuColBatchClass/getStudentAvailableBatches` +- **请求参数**: 无 +- **请求头**: 需要包含有效的Token + +### 响应格式 +```json +{ + "code": 200, + "msg": "操作成功", + "data": [ + { + "batchId": 1, + "batchName": "2025年春季学期信息收集", + "description": "收集学生基本信息", + "startTime": "2025-01-01 00:00:00", + "endTime": "2025-01-31 23:59:59", + "status": "0", + "collectionType": "1", + "remark": "新学期信息收集", + "classId": 101, + "className": "计算机科学与技术2021级1班", + "majorId": 1, + "majorName": "计算机科学与技术", + "collegeId": 1, + "collegeName": "信息工程学院" + } + ] +} +``` + +### 错误响应 +```json +{ + "code": 500, + "msg": "查询学生可参与批次信息失败:具体错误信息" +} +``` + +## 🧪 测试建议 + +### 功能测试 +1. **正常场景**: 登录学生用户,查询可参与的批次信息 +2. **无权限场景**: 未登录用户访问接口 +3. **无数据场景**: 学生没有可参与的批次 +4. **异常场景**: 数据库连接异常 + +### 数据验证 +1. 验证返回的批次信息是否正确 +2. 验证班级信息是否与当前用户匹配 +3. 验证批次状态是否为正常状态 +4. 验证数据排序是否正确(按开始时间倒序) + +## 📚 相关文档 + +- **API文档**: 学生信息收集批次管理API +- **数据库设计**: 学生信息收集批次管理表设计 +- **权限配置**: 菜单权限配置指南 + +## 🔄 后续优化建议 + +1. **缓存优化**: 考虑对批次信息进行缓存,提高查询性能 +2. **分页支持**: 如果批次数量较多,可以考虑添加分页功能 +3. **状态过滤**: 可以添加参数支持按批次状态过滤 +4. **时间范围**: 可以添加参数支持按时间范围查询 + +--- + +**开发完成时间**: 2025-01-17 +**代码审查**: 待审查 +**测试状态**: 待测试 +**部署状态**: 待部署 \ No newline at end of file diff --git a/docs/变更管理/code-adjust-record-2025-01-27-wuzilong.md b/docs/变更管理/code-adjust-record-2025-01-27-wuzilong.md index 119b675f..595501d7 100644 --- a/docs/变更管理/code-adjust-record-2025-01-27-wuzilong.md +++ b/docs/变更管理/code-adjust-record-2025-01-27-wuzilong.md @@ -1,149 +1,58 @@ -# 学生信息收集批次管理页面收集范围功能修复 +# 代码调整记录 - 2025-01-27 -**修改时间**: 2025-01-27 15:30:00 -**修改人**: wuzilong -**修改文件**: `web/src/views/XgStuColBatch/stuColBatch/index.vue` +## 修改时间 +2025-01-27 10:30:00 -## 问题描述 +## 修改人员 +wuzilong -在学生信息收集批次管理页面的收集范围功能中,存在以下问题: +## 修改内容 -1. **现象**: 第一次配置收集范围后(如配置11个权限),第二次配置时去掉其中一个勾选,第三次打开收集范围弹窗时,发现之前去掉勾选的权限又重新被勾选了 -2. **后台数据**: 从后台API接口看,数据只返回了10条(正确的),但前端显示仍然包含已取消的权限 -3. **根本原因**: 树形组件的勾选状态管理存在问题,历史勾选状态没有正确清空 +### 1. 学生信息完善页面 - 信息完善按钮显示逻辑优化 -## 解决方案 +**文件路径**: `web/src/views/stuMsgSupply/index.vue` -### 核心修改思路 -每次打开收集范围弹窗界面时,首先清空部门树的勾选项目,然后再将选择的内容回显。 +**修改内容**: +- 为信息完善按钮添加了条件显示逻辑 +- 新增 `isBatchValid` 方法用于检查批次有效性 +- 按钮只在以下条件同时满足时才显示: + - 批次状态为正常(status === '0') + - 当前时间在批次的有效时间范围内(startTime <= now <= endTime) -### 具体修改内容 +**具体修改**: +1. 在信息完善按钮的 `el-tooltip` 组件上添加 `v-if="isBatchValid(scope.row)"` 条件 +2. 新增 `isBatchValid` 方法: + ```javascript + const isBatchValid = (row: StuColBatchVO): boolean => { + // 检查状态是否为正常 + if (row.status !== '0') { + return false; + } + + // 检查是否在有效时间内 + const now = new Date(); + const startTime = new Date(row.startTime); + const endTime = new Date(row.endTime); + + return now >= startTime && now <= endTime; + }; + ``` -#### 1. 修改 `handleScope` 方法 -```javascript -/** 收集范围按钮操作 */ -const handleScope = async (row: StuColBatchVO) => { - currentBatch.value = row; - // 先清空勾选状态 - checkedDeptIds.value = []; - - await loadDeptTree(); - await loadCurrentScope(row.id); - scopeDialog.visible = true; - - // 使用nextTick确保DOM更新完成后再设置勾选状态 - await nextTick(); - if (scopeTreeRef.value && checkedDeptIds.value.length > 0) { - scopeTreeRef.value.setCheckedKeys(checkedDeptIds.value); - } -}; -``` +**业务价值**: +- 提升用户体验:避免用户在无效时间段内进行信息完善操作 +- 数据一致性:确保只有在有效批次内才能进行信息收集 +- 界面清晰:减少用户困惑,明确操作时机 -#### 2. 移除树形组件的 `:default-checked-keys` 属性 -```vue - - +**影响范围**: +- 学生信息完善页面的操作按钮显示逻辑 +- 不影响其他功能模块 - - -``` +## 测试建议 +1. 测试正常状态且在有效时间内的批次 - 按钮应正常显示 +2. 测试停用状态的批次 - 按钮应不显示 +3. 测试已过期的批次 - 按钮应不显示 +4. 测试未开始的批次 - 按钮应不显示 -#### 3. 添加弹窗关闭事件处理 -```vue - -``` - -#### 4. 新增 `handleScopeDialogClose` 方法 -```javascript -/** 处理收集范围弹窗关闭 */ -const handleScopeDialogClose = () => { - // 清空相关状态 - currentBatch.value = null; - checkedDeptIds.value = []; - // 清空树形组件的勾选状态 - if (scopeTreeRef.value) { - scopeTreeRef.value.setCheckedKeys([]); - } -}; -``` - -#### 5. 修改 `cancelScope` 方法 -```javascript -/** 取消收集范围设置 */ -const cancelScope = () => { - scopeDialog.visible = false; - currentBatch.value = null; - checkedDeptIds.value = []; - // 清空树形组件的勾选状态 - if (scopeTreeRef.value) { - scopeTreeRef.value.setCheckedKeys([]); - } -}; -``` - -#### 6. 修改 `submitScope` 方法 -```javascript -if (response && response.code === 200) { - ElMessage.success(response.msg || '收集范围设置成功'); - scopeDialog.visible = false; - // 提交成功后清空状态 - handleScopeDialogClose(); -} else { - ElMessage.error(response?.msg || '设置收集范围失败'); -} -``` - -## 技术要点 - -### 1. 状态管理优化 -- **问题**: 使用 `:default-checked-keys` 只在组件初始化时生效 -- **解决**: 改为手动调用 `setCheckedKeys()` 方法控制勾选状态 - -### 2. 时序控制 -- **问题**: DOM更新和状态设置的时序问题 -- **解决**: 使用 `nextTick()` 确保DOM更新完成后再设置勾选状态 - -### 3. 状态清理 -- **问题**: 弹窗关闭时状态没有完全清理 -- **解决**: 在弹窗关闭、取消、提交成功时都进行状态清理 - -## 测试验证 - -### 测试场景 -1. **首次配置**: 配置11个权限,保存成功 -2. **修改配置**: 去掉1个权限,保存成功 -3. **再次打开**: 验证只显示10个勾选,不包含已取消的权限 -4. **多次操作**: 重复上述操作,确保状态正确 - -### 预期结果 -- 每次打开弹窗时,勾选状态与后台数据完全一致 -- 历史勾选状态不会影响当前显示 -- 弹窗关闭后状态完全清理 - -## 影响范围 - -- **功能影响**: 仅影响收集范围功能的显示逻辑,不影响数据保存 -- **用户体验**: 修复了勾选状态显示错误的问题,提升用户体验 -- **代码质量**: 优化了状态管理逻辑,提高了代码的健壮性 - -## 相关文档 - -- 前端开发规范: `.cursor/cursorrules-frontend.md` -- 学生信息收集批次管理API文档: `docs/开发文档/API/学生信息收集批次管理API.md` \ No newline at end of file +## 备注 +- 该修改为前端显示逻辑优化,不影响后端API +- 建议后续可以考虑添加提示信息,告知用户为什么按钮不显示 \ No newline at end of file diff --git a/web/src/views/stuMsgSupply/index.vue b/web/src/views/stuMsgSupply/index.vue index 69903739..db6914bd 100644 --- a/web/src/views/stuMsgSupply/index.vue +++ b/web/src/views/stuMsgSupply/index.vue @@ -86,6 +86,12 @@ v-hasPermi="['XgStuColBatch:stuColBatch:query']" > + + + + + +