# 勤工俭学岗位管理API修改说明 ## 📋 修改概述 **修改日期**: 2025-08-12 **修改目标**: 重构勤工俭学岗位申请列表API,实现更合理的路由设计和权限管理 ## 🎯 问题分析 ### 原有问题 1. **语义混乱**: 申请模块的 `/jcbt/workStudyApplication/list` 返回的是岗位列表,而不是申请列表 2. **权限设计不合理**: 岗位管理模块已经有 `jcbt:workStudyPosition:visibleList` 权限,申请模块却用自己的权限去查询岗位 3. **代码重复**: 两个模块都在查询岗位数据,逻辑重复 ### 修改方案 采用**方案一**:使用岗位模块的 `visibleList` 接口,添加 `excludeApplied` 参数 ## 🔧 具体修改 ### 1. 后端修改 #### 1.1 岗位管理控制器 (JcbtWorkStudyPositionController) **修改方法**: `visibleList` ```java /** * 可见岗位 - 查询学院可见的岗位(本学院岗位 + 全校范围岗位) */ @Operation(summary = "可见岗位") @SaCheckPermission("jcbt:workStudyPosition:visibleList") @GetMapping("/visibleList") public TableDataInfo visibleList( JcbtWorkStudyPositionBo bo, PageQuery pageQuery, @Parameter(description = "是否排除已申请岗位") @RequestParam(defaultValue = "false") Boolean excludeApplied) { // 获取当前用户所在学院ID Long collegeId = getCurrentUserCollegeId(); Long userId = null; if (excludeApplied) { // 排除当前用户已申请的岗位 - 用于学生申请页面 userId = LoginHelper.getUserId(); if (userId == null) { return TableDataInfo.build(); } // 查询学生信息获取学院ID(覆盖默认学院ID) try { XgStudentMsgVo studentInfo = xgStudentMsgService.queryByUserId(userId); if (studentInfo != null && studentInfo.getCollegeId() != null) { collegeId = Long.parseLong(studentInfo.getCollegeId()); } } catch (Exception e) { log.warn("获取学生学院ID失败: {}", e.getMessage()); } } // 统一调用重载的方法 return workStudyPositionService.queryVisiblePositions(bo, pageQuery, collegeId, excludeApplied, userId); } ``` **新增依赖**: - `XgStudentMsgVo` - `IXgStudentMsgService` #### 1.2 服务接口 (IJcbtWorkStudyPositionService) **新增方法**: ```java /** * 查询学院可见的岗位(本学院岗位 + 全校范围岗位)- 支持查询条件和排除已申请岗位 * * @param bo 查询条件 * @param pageQuery 分页参数 * @param collegeId 学院ID * @param excludeApplied 是否排除已申请岗位 * @param userId 用户ID(当排除已申请岗位时需要) * @return 可见岗位列表 */ TableDataInfo queryVisiblePositions(JcbtWorkStudyPositionBo bo, PageQuery pageQuery, Long collegeId, Boolean excludeApplied, Long userId); ``` #### 1.3 服务实现 (JcbtWorkStudyPositionServiceImpl) **新增实现**: ```java @Override public TableDataInfo queryVisiblePositions(JcbtWorkStudyPositionBo bo, PageQuery pageQuery, Long collegeId, Boolean excludeApplied, Long userId) { if (excludeApplied && userId != null) { // 排除已申请岗位的情况,直接调用现有的方法 return queryAvailablePositionsForStudent(bo, pageQuery, collegeId); } else { // 普通的可见岗位查询 return queryVisiblePositions(collegeId, pageQuery); } } ``` #### 1.4 申请管理控制器 (JcbtWorkStudyApplicationController) **删除方法**: `list()` - 原来用于查询岗位列表的方法 **删除依赖**: 不再需要的岗位相关服务和VO类 ### 2. 前端修改 #### 2.1 API定义 (workStudyPosition.ts) **新增方法**: ```typescript /** * 查询可见岗位列表(学院可见的岗位:本学院岗位 + 全校范围岗位) * @param query 查询参数 * @param excludeApplied 是否排除已申请岗位 */ export function listVisiblePositions(query: WorkStudyPositionQuery, excludeApplied: boolean = false): AxiosPromise> { return request({ url: '/jcbt/workStudyPosition/visibleList', method: 'get', params: { ...query, excludeApplied } }); } ``` #### 2.2 页面调用 (Application/index.vue) **修改导入**: ```typescript // 原来 import { listWorkStudyPosition } from '@/api/jcbt/workStudyPosition' // 修改为 import { listVisiblePositions } from '@/api/jcbt/workStudyPosition' ``` **修改调用**: ```typescript /** 查询岗位列表 */ const getPositionList = async () => { loading.value = true try { // 调用可见岗位接口,排除已申请的岗位 const response = await listVisiblePositions(queryParams, true) // 后端返回 TableDataInfo 结构,响应拦截器已解包,直接使用 response.rows positionList.value = response.rows || [] total.value = response.total || 0 } catch (error) { console.error('获取岗位列表失败:', error) ElMessage.error('获取岗位列表失败') } finally { loading.value = false } } ``` ## 🎯 修改效果 ### 1. 路由更合理 - **学生申请页面**: `GET /jcbt/workStudyPosition/visibleList?excludeApplied=true` - **管理员查看**: `GET /jcbt/workStudyPosition/visibleList?excludeApplied=false` ### 2. 权限统一 - 统一使用 `jcbt:workStudyPosition:visibleList` 权限 - 学生角色需要有这个权限才能查看可申请岗位 ### 3. 功能增强 - ✅ **智能过滤**: 自动识别用户身份,过滤已申请岗位 - ✅ **状态感知**: 只排除未取消和未被最终拒绝的申请 - ✅ **权限控制**: 结合学院权限和申请状态双重过滤 - ✅ **实时更新**: 申请提交后,岗位列表会自动更新 ## 📋 API接口说明 ### visibleList - 可见岗位列表 **接口地址**: `GET /jcbt/workStudyPosition/visibleList` **权限要求**: `jcbt:workStudyPosition:visibleList` **请求参数**: | 参数名 | 类型 | 必填 | 默认值 | 说明 | |--------|------|------|--------|------| | excludeApplied | Boolean | 否 | false | 是否排除已申请岗位 | | positionName | String | 否 | - | 岗位名称 | | positionScope | String | 否 | - | 发布范围 | | contactTeacher | String | 否 | - | 联系老师 | | pageNum | Integer | 否 | 1 | 页码 | | pageSize | Integer | 否 | 10 | 每页数量 | **响应数据**: ```json { "code": 200, "msg": "操作成功", "total": 10, "rows": [ { "id": 1, "positionName": "图书管理员", "positionScope": "COLLEGE", "requiredCount": 5, "currentCount": 2, "status": "RECRUITING", "collegeName": "计算机学院" } ] } ``` ## 🔄 过滤规则 当 `excludeApplied=true` 时,系统会过滤掉以下岗位: 1. 当前用户已经申请的岗位 2. 申请状态为 `CANCELLED`(已取消)或 `FINAL_REJECTED`(最终拒绝)的除外 **SQL逻辑**: ```sql AND NOT EXISTS ( SELECT 1 FROM jcbt_work_study_application app WHERE app.position_id = jcbt_work_study_position.id AND app.student_id = #{当前用户ID} AND app.status NOT IN ('CANCELLED', 'FINAL_REJECTED') AND app.deleted = 0 ) ``` ## ✅ 验证方法 1. **登录不同用户**: 验证过滤结果的个性化 2. **申请岗位**: 确认申请后该岗位从列表中消失 3. **取消申请**: 确认取消后岗位重新出现在列表中 ## 📝 注意事项 1. **权限配置**: 确保学生角色有 `jcbt:workStudyPosition:visibleList` 权限 2. **学院ID获取**: 系统会自动从学生信息中获取学院ID,如果获取失败会使用默认值 3. **向下兼容**: 原有的 `visibleList` 接口(不带 `excludeApplied` 参数)仍然可用 ## 🎯 总结 通过这次重构,实现了: - ✅ **语义清晰**: 查询岗位就用岗位模块的接口 - ✅ **权限统一**: 岗位相关权限都在岗位模块管理 - ✅ **代码复用**: 避免重复的岗位查询逻辑 - ✅ **架构清晰**: 每个模块职责明确 - ✅ **功能增强**: 支持智能过滤已申请岗位