|
|
@@ -0,0 +1,250 @@
|
|
|
+# 学院请假审批人查询API接口实现变更记录
|
|
|
+
|
|
|
+**变更日期**: 2025-01-27
|
|
|
+**变更人员**: AI Assistant
|
|
|
+**变更类型**: 功能新增
|
|
|
+
|
|
|
+## 📋 变更概述
|
|
|
+
|
|
|
+在学生信息管理模块中新增了一个API接口,用于根据学生ID查询所在学院的请假审批人列表。
|
|
|
+
|
|
|
+## 🎯 业务需求
|
|
|
+
|
|
|
+- 接口入参:studentId(学生ID)
|
|
|
+- 业务逻辑:
|
|
|
+ 1. 通过xg_student_msg.id关联入参studentId学生id,deleted = 0,获取到college_id
|
|
|
+ 2. 从sys_user表中,找到college_id对应的组织及子组织下,具备xsqj-ejxyspr这个角色的人员list
|
|
|
+ 3. 查询条件:
|
|
|
+ - sys_dept是组织表:del_flag = 0, status = 0
|
|
|
+ - sys_user是用户表:del_flag = 0, status = 0, account_type = 1
|
|
|
+ - sys_user_role是用户与角色的关联表
|
|
|
+ - sys_role是角色表:role_key = 'xsqj-ejxyspr'
|
|
|
+- 返回结果:请假审批人用户ID列表
|
|
|
+
|
|
|
+## 🔧 技术实现
|
|
|
+
|
|
|
+### 1. Mapper接口扩展
|
|
|
+**文件**: `backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/mapper/XgStudentMsgMapper.java`
|
|
|
+
|
|
|
+```java
|
|
|
+/**
|
|
|
+ * 根据学生ID查询学院ID
|
|
|
+ *
|
|
|
+ * @param studentId 学生ID
|
|
|
+ * @return 学院ID
|
|
|
+ */
|
|
|
+Long selectCollegeIdByStudentId(@Param("studentId") Long studentId);
|
|
|
+
|
|
|
+/**
|
|
|
+ * 根据学院ID和角色Key查询具备该角色的用户列表
|
|
|
+ *
|
|
|
+ * @param collegeId 学院ID
|
|
|
+ * @param roleKey 角色Key
|
|
|
+ * @return 用户ID列表
|
|
|
+ */
|
|
|
+List<Long> selectUserIdsByCollegeIdAndRoleKey(@Param("collegeId") Long collegeId, @Param("roleKey") String roleKey);
|
|
|
+```
|
|
|
+
|
|
|
+### 2. Mapper XML SQL实现
|
|
|
+**文件**: `backend/ruoyi-modules/ruoyi-xg/src/main/resources/mapper/studentMsg/XgStudentMsgMapper.xml`
|
|
|
+
|
|
|
+```xml
|
|
|
+<!-- 根据学生ID查询学院ID -->
|
|
|
+<select id="selectCollegeIdByStudentId" resultType="java.lang.Long">
|
|
|
+ SELECT college_id
|
|
|
+ FROM xg_student_msg
|
|
|
+ WHERE id = #{studentId}
|
|
|
+ AND deleted = 0
|
|
|
+</select>
|
|
|
+
|
|
|
+<!-- 根据学院ID和角色Key查询具备该角色的用户列表 -->
|
|
|
+<select id="selectUserIdsByCollegeIdAndRoleKey" resultType="java.lang.Long">
|
|
|
+ SELECT DISTINCT u.user_id
|
|
|
+ FROM sys_user u
|
|
|
+ INNER JOIN sys_user_role ur ON u.user_id = ur.user_id
|
|
|
+ INNER JOIN sys_role r ON ur.role_id = r.role_id
|
|
|
+ INNER JOIN sys_dept d ON u.dept_id = d.dept_id
|
|
|
+ WHERE u.del_flag = '0'
|
|
|
+ AND u.status = '0'
|
|
|
+ AND u.account_type = '1'
|
|
|
+ AND d.del_flag = '0'
|
|
|
+ AND d.status = '0'
|
|
|
+ AND r.role_key = #{roleKey}
|
|
|
+ AND (d.dept_id = #{collegeId} OR FIND_IN_SET(#{collegeId}, d.ancestors))
|
|
|
+</select>
|
|
|
+```
|
|
|
+
|
|
|
+### 3. Service接口扩展
|
|
|
+**文件**: `backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/IXgStudentMsgService.java`
|
|
|
+
|
|
|
+```java
|
|
|
+/**
|
|
|
+ * 根据学生ID获取学院请假审批人列表
|
|
|
+ *
|
|
|
+ * @param studentId 学生ID
|
|
|
+ * @return 请假审批人用户ID列表
|
|
|
+ */
|
|
|
+List<Long> getCollegeLeaveApproversByStudentId(Long studentId);
|
|
|
+```
|
|
|
+
|
|
|
+### 4. Service实现类扩展
|
|
|
+**文件**: `backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgStudentMsgServiceImpl.java`
|
|
|
+
|
|
|
+```java
|
|
|
+/**
|
|
|
+ * 根据学生ID获取学院请假审批人列表
|
|
|
+ *
|
|
|
+ * @param studentId 学生ID
|
|
|
+ * @return 请假审批人用户ID列表
|
|
|
+ */
|
|
|
+@Override
|
|
|
+public List<Long> getCollegeLeaveApproversByStudentId(Long studentId) {
|
|
|
+ log.info("根据学生ID获取学院请假审批人列表 - 学生ID: {}", studentId);
|
|
|
+
|
|
|
+ // 1. 根据学生ID查询学院ID
|
|
|
+ Long collegeId = baseMapper.selectCollegeIdByStudentId(studentId);
|
|
|
+ if (collegeId == null) {
|
|
|
+ log.warn("未找到学生对应的学院信息 - 学生ID: {}", studentId);
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("学生所在学院ID: {}", collegeId);
|
|
|
+
|
|
|
+ // 2. 根据学院ID和角色Key查询具备请假审批角色的用户列表
|
|
|
+ List<Long> approverUserIds = baseMapper.selectUserIdsByCollegeIdAndRoleKey(collegeId, "xsqj-ejxyspr");
|
|
|
+
|
|
|
+ log.info("找到的请假审批人数量: {}", approverUserIds.size());
|
|
|
+ return approverUserIds;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 5. Controller API接口
|
|
|
+**文件**: `backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/controller/XgStudentMsgController.java`
|
|
|
+
|
|
|
+```java
|
|
|
+/**
|
|
|
+ * 根据学生ID获取学院请假审批人列表
|
|
|
+ *
|
|
|
+ * @param studentId 学生ID
|
|
|
+ * @return 请假审批人用户ID列表
|
|
|
+ */
|
|
|
+@SaCheckPermission("studentMsg:studentMsg:query")
|
|
|
+@GetMapping("/getCollegeLeaveApprovers/{studentId}")
|
|
|
+public R<List<Long>> getCollegeLeaveApprovers(@NotNull(message = "学生ID不能为空") @PathVariable Long studentId) {
|
|
|
+ log.info("根据学生ID获取学院请假审批人列表 - 学生ID: {}", studentId);
|
|
|
+ List<Long> approverUserIds = xgStudentMsgService.getCollegeLeaveApproversByStudentId(studentId);
|
|
|
+ if (approverUserIds.isEmpty()) {
|
|
|
+ return R.fail("未找到该学生所在学院的请假审批人");
|
|
|
+ }
|
|
|
+ return R.ok(approverUserIds);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+## 📡 API接口详情
|
|
|
+
|
|
|
+### 接口信息
|
|
|
+- **请求路径**: `GET /studentMsg/studentMsg/getCollegeLeaveApprovers/{studentId}`
|
|
|
+- **权限要求**: `studentMsg:studentMsg:query`
|
|
|
+- **入参**: studentId (路径参数,Long类型)
|
|
|
+- **返回**: R<List<Long>> 统一响应格式
|
|
|
+
|
|
|
+### 请求示例
|
|
|
+```
|
|
|
+GET /studentMsg/studentMsg/getCollegeLeaveApprovers/123456
|
|
|
+```
|
|
|
+
|
|
|
+### 响应示例
|
|
|
+**成功响应**:
|
|
|
+```json
|
|
|
+{
|
|
|
+ "code": 200,
|
|
|
+ "msg": "操作成功",
|
|
|
+ "data": [789012, 789013, 789014]
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**失败响应**:
|
|
|
+```json
|
|
|
+{
|
|
|
+ "code": 500,
|
|
|
+ "msg": "未找到该学生所在学院的请假审批人",
|
|
|
+ "data": null
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+## 🔍 数据库查询逻辑
|
|
|
+
|
|
|
+### 第一步:查询学生所在学院ID
|
|
|
+```sql
|
|
|
+SELECT college_id
|
|
|
+FROM xg_student_msg
|
|
|
+WHERE id = #{studentId}
|
|
|
+ AND deleted = 0
|
|
|
+```
|
|
|
+
|
|
|
+### 第二步:查询学院及子组织下具备请假审批角色的用户
|
|
|
+```sql
|
|
|
+SELECT DISTINCT u.user_id
|
|
|
+FROM sys_user u
|
|
|
+INNER JOIN sys_user_role ur ON u.user_id = ur.user_id
|
|
|
+INNER JOIN sys_role r ON ur.role_id = r.role_id
|
|
|
+INNER JOIN sys_dept d ON u.dept_id = d.dept_id
|
|
|
+WHERE u.del_flag = '0'
|
|
|
+ AND u.status = '0'
|
|
|
+ AND u.account_type = '1'
|
|
|
+ AND d.del_flag = '0'
|
|
|
+ AND d.status = '0'
|
|
|
+ AND r.role_key = 'xsqj-ejxyspr'
|
|
|
+ AND (d.dept_id = #{collegeId} OR FIND_IN_SET(#{collegeId}, d.ancestors))
|
|
|
+```
|
|
|
+
|
|
|
+## 📊 表关联关系
|
|
|
+
|
|
|
+1. **xg_student_msg** (学生信息表) → college_id
|
|
|
+2. **sys_dept** (部门表) → dept_id, ancestors (祖级列表)
|
|
|
+3. **sys_user** (用户表) → dept_id, user_id
|
|
|
+4. **sys_user_role** (用户角色关联表) → user_id, role_id
|
|
|
+5. **sys_role** (角色表) → role_id, role_key
|
|
|
+
|
|
|
+## ✅ 实现特点
|
|
|
+
|
|
|
+1. **数据完整性**: 确保只查询未删除的学生、用户、部门和角色信息
|
|
|
+2. **权限控制**: 使用@SaCheckPermission注解进行权限验证
|
|
|
+3. **参数验证**: 使用@NotNull注解验证入参
|
|
|
+4. **日志记录**: 添加详细的日志记录便于调试
|
|
|
+5. **错误处理**: 当未找到审批人时返回友好的错误提示
|
|
|
+6. **统一响应**: 使用R<List<Long>>统一响应格式
|
|
|
+7. **组织层级**: 支持查询学院及其子组织下的审批人
|
|
|
+8. **角色过滤**: 精确匹配角色Key为'xsqj-ejxyspr'的用户
|
|
|
+
|
|
|
+## 🧪 测试建议
|
|
|
+
|
|
|
+1. **正常场景测试**:
|
|
|
+ - 使用存在的学生ID测试
|
|
|
+ - 验证返回的审批人列表
|
|
|
+2. **异常场景测试**:
|
|
|
+ - 使用不存在的学生ID
|
|
|
+ - 使用已删除的学生ID
|
|
|
+ - 使用空值或无效值
|
|
|
+ - 测试学院下没有审批人的情况
|
|
|
+3. **权限测试**: 验证权限控制是否生效
|
|
|
+4. **数据完整性测试**: 验证查询条件是否正确过滤
|
|
|
+
|
|
|
+## 📝 相关文档
|
|
|
+
|
|
|
+- 学生信息管理API文档: `docs/开发文档/API/学生信息管理API.md`
|
|
|
+- 学生信息表结构: `docs/设计文档/database/学工管理-学生信息管理新版/xg_student_msg 学生信息表.sql`
|
|
|
+- 系统用户表结构: `docs/设计文档/database/学工管理-学生信息管理/05-system-management-module.sql`
|
|
|
+
|
|
|
+## 🔧 技术要点
|
|
|
+
|
|
|
+1. **FIND_IN_SET函数**: 用于查询ancestors字段中是否包含指定的学院ID
|
|
|
+2. **DISTINCT去重**: 避免重复的用户ID
|
|
|
+3. **多表关联**: 通过INNER JOIN关联用户、角色、部门表
|
|
|
+4. **条件过滤**: 严格按照业务要求过滤有效数据
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+**变更完成时间**: 2025-01-27
|
|
|
+**变更状态**: ✅ 已完成
|
|
|
+**下一步**: 进行功能测试和API文档更新
|