轻松聘AI开发
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

6.5 KiB

求职者评分卡 API

概述

求职者评价聚合与评分卡模块,提供求职者(STUDENT)查看自己的评价聚合数据、评分趋势和百分位排名。

权限

  • 未登录:HTTP 401(code=401)
  • STUDENT:HTTP 200
  • COMPANY:HTTP 403(code=2002)
  • ADMIN:HTTP 403(code=2002)

所有接口只允许当前登录的 STUDENT 查询自己的数据,不接受通过 URL 参数查询其他用户。

接口列表

1. GET /api/v1/profile/me/candidate-score-card

查询求职者评分卡。

响应示例(有数据):

{
  "code": 200,
  "message": "ok",
  "data": {
    "candidateId": 10001,
    "status": "OK",
    "overallScore": null,
    "sampleCount": 3,
    "feedbackSummary": {
      "totalCount": 3,
      "averageRating": 4.33,
      "ratingDistribution": {
        "1": 0,
        "2": 0,
        "3": 1,
        "4": 0,
        "5": 2
      },
      "tags": [
        {"name": "沟通良好", "count": 2}
      ]
    },
    "matchSignals": {
      "candidateInterestScore": {
        "average": 82.50,
        "sampleCount": 2
      },
      "hrSuitabilityScore": {
        "average": 76.00,
        "sampleCount": 1
      }
    },
    "unsupportedDimensions": [
      "EDUCATION", "INTERNSHIP", "ABILITY", "COMPLIANCE",
      "STABILITY", "GROWTH", "INTEGRITY", "ACTIVITY"
    ],
    "generatedAt": "2026-08-14T12:00:00Z"
  }
}

响应示例(无数据):

{
  "code": 200,
  "message": "ok",
  "data": {
    "candidateId": 10001,
    "status": "INSUFFICIENT_DATA",
    "overallScore": null,
    "sampleCount": 0,
    "feedbackSummary": {
      "totalCount": 0,
      "averageRating": null,
      "ratingDistribution": {
        "1": 0, "2": 0, "3": 0, "4": 0, "5": 0
      },
      "tags": []
    },
    "matchSignals": {
      "candidateInterestScore": {"average": null, "sampleCount": 0},
      "hrSuitabilityScore": {"average": null, "sampleCount": 0}
    },
    "unsupportedDimensions": [
      "EDUCATION", "INTERNSHIP", "ABILITY", "COMPLIANCE",
      "STABILITY", "GROWTH", "INTEGRITY", "ACTIVITY"
    ],
    "generatedAt": "2026-08-14T12:00:00Z"
  }
}

错误响应:

  • 未登录:401(code=401)
  • 非 STUDENT:403(code=2002)

2. GET /api/v1/profile/me/candidate-score-trend

查询评分趋势。

参数:

参数 类型 必填 默认值 说明
months int 否 6 统计月数,范围 1-24

响应示例:

{
  "code": 200,
  "message": "ok",
  "data": {
    "candidateId": 10001,
    "months": 6,
    "items": [
      {
        "month": "2026-03",
        "feedbackCount": 2,
        "averageRating": 4.50,
        "ratingScore": 90.00
      }
    ]
  }
}

错误响应:

  • 未登录:401(code=401)
  • 非 STUDENT:403(code=2002)
  • months < 1 或 > 24:400(code=1001)

说明:

  • 趋势时间范围:months=6 表示当前月份和前 5 个自然月,起始时间使用当前月份的第一天
  • 按 candidate_feedback.created_at 的年月分组,结果按 yyyy-MM 升序
  • ratingScore = averageRating / 5 * 100,保留两位小数
  • 无数据时返回 items: [](没有数据的月份不返回空月份条目)

3. GET /api/v1/profile/me/candidate-percentile

查询评分百分位。

响应示例(有数据):

{
  "code": 200,
  "message": "ok",
  "data": {
    "candidateId": 10001,
    "status": "OK",
    "scoreType": "FEEDBACK_RATING",
    "score": 86.67,
    "percentile": 72.50,
    "cohortSize": 38,
    "sampleCount": 3,
    "minimumSampleCount": 3
  }
}

响应示例(样本不足):

{
  "code": 200,
  "message": "ok",
  "data": {
    "candidateId": 10001,
    "status": "INSUFFICIENT_DATA",
    "scoreType": "FEEDBACK_RATING",
    "score": null,
    "percentile": null,
    "cohortSize": 0,
    "sampleCount": 1,
    "minimumSampleCount": 3
  }
}

错误响应:

  • 未登录:401(code=401)
  • 非 STUDENT:403(code=2002)

百分位计算公式

cohort 定义:

  • candidate_feedback 按 student_user_id 分组
  • COUNT(*) >= 3 的求职者进入 cohort

score 计算:

  • score = AVG(rating) / 5 * 100

百分位计算:

  • percentile = COUNT(other.score < current.score) / (cohortSize - 1) * 100
  • 只统计严格低于当前分数的求职者
  • 最高分为 100.00
  • 最低分为 0.00
  • 同分不互相计入
  • 使用 BigDecimal,保留两位小数,HALF_UP

INSUFFICIENT_DATA 条件:

  • 当前用户反馈数 < 3
  • cohort 总人数 < 2

不支持的评分维度

当前评分卡仅覆盖基于反馈的评分聚合,以下 8 个维度尚未实现,始终返回为 unsupportedDimensions:

  • EDUCATION(教育背景)
  • INTERNSHIP(实习经历)
  • ABILITY(能力评分)
  • COMPLIANCE(合规性)
  • STABILITY(稳定性)
  • GROWTH(成长潜力)
  • INTEGRITY(诚信评分)
  • ACTIVITY(求职活跃度)

overallScore 在 8 个维度全部实现前固定为 null。

数据来源

数据 来源表
反馈总数、平均评分、评分分布 candidate_feedback
标签聚合 candidate_feedback.tags(JSON)
求职者意愿分、HR 适配分 application_match_records
趋势 candidate_feedback.created_at
百分位 candidate_feedback 全量聚合

null 字段策略

项目全局配置 spring.jackson.default-property-inclusion=non_null,null 字段默认不序列化。

以下关键字段使用 @JsonInclude(JsonInclude.Include.ALWAYS) 标注,无数据时仍显式返回 null:

  • overallScore(评分卡)
  • averageRating(feedbackSummary)
  • candidateInterestScore.average(匹配信号)
  • hrSuitabilityScore.average(匹配信号)
  • score(百分位)
  • percentile(百分位)

查询次数

评分卡三个接口的实际 SQL 查询次数:

接口 查询次数 说明
GET /profile/me/candidate-score-card 4 条 SQL 1 反馈摘要(COUNT+AVG合并) + 1 评分分布 + 1 标签 + 2 匹配信号(candidateInterestScore + hrSuitabilityScore)
GET /profile/me/candidate-score-trend 1 条 SQL 按月聚合趋势
GET /profile/me/candidate-percentile 3 条 SQL cohort 人数 + 当前分数 + 排名(仅当样本>=3 且 cohort>=2 时执行全部 3 条)

所有查询均针对单个 studentUserId,无 N+1 问题。

数据脱敏

  • 不返回 candidate_feedback.content
  • 不返回 companyUserId
  • 不返回 applicationId
  • 不返回其他求职者的任何数据
  • 不暴露内部审核字段