勤工俭学岗位管理API修改说明.md 8.0 KB

勤工俭学岗位管理API修改说明

📋 修改概述

修改日期: 2025-08-12
修改目标: 重构勤工俭学岗位申请列表API,实现更合理的路由设计和权限管理

🎯 问题分析

原有问题

  1. 语义混乱: 申请模块的 /jcbt/workStudyApplication/list 返回的是岗位列表,而不是申请列表
  2. 权限设计不合理: 岗位管理模块已经有 jcbt:workStudyPosition:visibleList 权限,申请模块却用自己的权限去查询岗位
  3. 代码重复: 两个模块都在查询岗位数据,逻辑重复

修改方案

采用方案一:使用岗位模块的 visibleList 接口,添加 excludeApplied 参数

🔧 具体修改

1. 后端修改

1.1 岗位管理控制器 (JcbtWorkStudyPositionController)

修改方法: visibleList

/**
 * 可见岗位 - 查询学院可见的岗位(本学院岗位 + 全校范围岗位)
 */
@Operation(summary = "可见岗位")
@SaCheckPermission("jcbt:workStudyPosition:visibleList")
@GetMapping("/visibleList")
public TableDataInfo<JcbtWorkStudyPositionVo> 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)

新增方法:

/**
 * 查询学院可见的岗位(本学院岗位 + 全校范围岗位)- 支持查询条件和排除已申请岗位
 *
 * @param bo 查询条件
 * @param pageQuery 分页参数
 * @param collegeId 学院ID
 * @param excludeApplied 是否排除已申请岗位
 * @param userId 用户ID(当排除已申请岗位时需要)
 * @return 可见岗位列表
 */
TableDataInfo<JcbtWorkStudyPositionVo> queryVisiblePositions(JcbtWorkStudyPositionBo bo, PageQuery pageQuery, Long collegeId, Boolean excludeApplied, Long userId);

1.3 服务实现 (JcbtWorkStudyPositionServiceImpl)

新增实现:

@Override
public TableDataInfo<JcbtWorkStudyPositionVo> 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)

新增方法:

/**
 * 查询可见岗位列表(学院可见的岗位:本学院岗位 + 全校范围岗位)
 * @param query 查询参数
 * @param excludeApplied 是否排除已申请岗位
 */
export function listVisiblePositions(query: WorkStudyPositionQuery, excludeApplied: boolean = false): AxiosPromise<TableDataInfo<WorkStudyPositionVO>> {
  return request({
    url: '/jcbt/workStudyPosition/visibleList',
    method: 'get',
    params: {
      ...query,
      excludeApplied
    }
  });
}

2.2 页面调用 (Application/index.vue)

修改导入:

// 原来
import { listWorkStudyPosition } from '@/api/jcbt/workStudyPosition'

// 修改为
import { listVisiblePositions } from '@/api/jcbt/workStudyPosition'

修改调用:

/** 查询岗位列表 */
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 | 每页数量 |

响应数据:

{
  "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逻辑:

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 参数)仍然可用

🎯 总结

通过这次重构,实现了:

  • ✅ 语义清晰: 查询岗位就用岗位模块的接口
  • ✅ 权限统一: 岗位相关权限都在岗位模块管理
  • ✅ 代码复用: 避免重复的岗位查询逻辑
  • ✅ 架构清晰: 每个模块职责明确
  • ✅ 功能增强: 支持智能过滤已申请岗位