轻松聘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.
 
 
 

8.8 KiB

企业评分运营看板 API

企业评分运营看板 / 评分排名 / 评分趋势 v0.1 基础路径:/api/v1 · 全部接口需 Authorization: Bearer <accessToken>

概述

  • 只读聚合:仅查询 jobs / applications / job_reviews / job_review_dimension_scores / candidate_dimension_scores 等业务表,不写入任何业务表、不产生新快照。
  • 候选人按学生去重:同一学生多次投递视为 1 名候选人,代表投递取该企业下该学生 applicationId 最大的一条;WITHDRAWN / REJECTED 投递排除在统计外。
  • 候选人综合分复用 CandidateScoringCalculator.overallScoreFromSnapshots:读取每个候选人 <= asOfPeriod(当前月)的最新期维度快照,用引擎公式计算;无可计算维度时 overallScore=null。
  • 岗位评价过滤与 JobReviewService.getReviewSummary 口径一致:status='PUBLISHED' 且 moderation_status IN ('AUTO_APPROVED','APPROVED')。
  • 企业数据隔离:companyId 从 JWT 推导(companyRepository.findByOwnerUserId),所有 SQL 限定 company_id,不接受请求参数传入企业 ID。

接口列表

# 方法 路径 角色 说明
1 GET /company/scoring/dashboard/overview COMPANY 企业评分运营概览
2 GET /company/scoring/dashboard/job-rankings?page&size COMPANY 岗位评分排名(分页)
3 GET /company/scoring/dashboard/job-rankings/{jobId} COMPANY 单岗位评分排名明细
4 GET /company/scoring/dashboard/candidate-rankings?page&size COMPANY 候选人评分排名(按学生去重,分页)
5 GET /company/scoring/dashboard/candidate-rankings/{applicationId} COMPANY 单候选人评分排名明细
6 GET /company/scoring/dashboard/trend?months=6 COMPANY 企业评分趋势(按月)
7 GET /admin/scoring/dashboard/overview ADMIN 全局运营概览

权限矩阵

接口 未登录 STUDENT COMPANY ADMIN
企业看板 6 接口 401 403 ✅(本企业) 403
全局概览 401 403 403 ✅

企业归属校验(单条详情):

  • 岗位不存在 → JOB_NOT_FOUND(7001) → 404;
  • 岗位不属于本企业 → JOB_OWNER_MISMATCH(7002) → 400;
  • 投递不存在 → APPLICATION_NOT_FOUND(8002) → 404;
  • 投递岗位不属于本企业 → APPLICATION_OWNER_MISMATCH(8004) → 403。

1. 企业评分运营概览

GET /company/scoring/dashboard/overview

响应

{
  "code": 200,
  "message": "ok",
  "data": {
    "companyId": 1,
    "totalJobs": 5,
    "publishedJobs": 3,
    "avgJobScore": 4.50,
    "totalCandidates": 3,
    "avgCandidateScore": 80.00,
    "scoreDistribution": { "1": 0, "2": 0, "3": 1, "4": 2, "5": 2 },
    "updatedAt": "2026-08-21T10:00:00"
  }
}
  • totalJobs:本企业岗位总数;publishedJobs:PUBLISHED 岗位数。
  • avgJobScore:审核通过评价的均值(无评价 → null)。
  • totalCandidates:管线内去重候选人(含无分);avgCandidateScore:有分候选人综合分均值(无 → null)。
  • scoreDistribution:1–5 星评价分布,全键恒存在(无评价为 0)。

2. 岗位评分排名

GET /company/scoring/dashboard/job-rankings?page=0&size=20
参数 类型 必填 默认 说明
page int 否 0 页码 (0-based)
size int 否 20 每页条数 (1–100)

page<0 或 size<1 || size>100 → 400 / 1001。

排序:avgRating DESC, jobId DESC(无评价岗位 avgRating=null 排在末尾);rank 为 1-based,cohortSize 为本企业岗位总数。

响应

{
  "code": 200,
  "message": "ok",
  "data": {
    "items": [{
      "jobId": 10,
      "title": "Java 后端工程师",
      "city": "北京",
      "employmentType": "FULL_TIME",
      "avgRating": 4.50,
      "reviewCount": 12,
      "rank": 1,
      "cohortSize": 5,
      "dimensionAverages": { "AUTHENTICITY": 4.50, "TEAM_ATMOSPHERE": 4.20 }
    }],
    "total": 5,
    "page": 0,
    "size": 20,
    "totalPages": 1
  }
}

dimensionAverages:审核通过评价的八维均值(dimension_code → avg(score),scale 2)。

3. 单岗位评分排名明细

GET /company/scoring/dashboard/job-rankings/{jobId}

返回结构与列表项一致(rank 在本企业内计算)。跨企业 → 400 / 7002。

4. 候选人评分排名

GET /company/scoring/dashboard/candidate-rankings?page=0&size=20
参数 类型 必填 默认 说明
page int 否 0 页码 (0-based)
size int 否 20 每页条数 (1–100)

page<0 或 size<1 || size>100 → 400 / 1001。

排序:overallScore DESC, applicationId DESC;percentile 在有分候选人集合内计算(升序百分位 = 小于自己的人数 / (有分人数-1) × 100,scale 2,overallScore=null → null)。

响应

{
  "code": 200,
  "message": "ok",
  "data": {
    "items": [{
      "applicationId": 30,
      "jobId": 10,
      "candidateName": "张三",
      "candidateSchool": "清华大学",
      "overallScore": 90.00,
      "percentile": 100.00,
      "sampleCount": 3
    }],
    "total": 3,
    "page": 0,
    "size": 20,
    "totalPages": 1
  }
}
  • applicationId 为代表投递(该学生在企业下最大 applicationId);candidateName/candidateSchool 取 student_profiles。
  • sampleCount:有分候选人总数(不分页)。

5. 单候选人评分排名明细

GET /company/scoring/dashboard/candidate-rankings/{applicationId}
  • 投递不存在 → 404 / 8002;投递岗位不属于本企业 → 403 / 8004;投递状态为 WITHDRAWN/REJECTED → 404 / 8002。
  • 若该候选人快照缺失,仍返回其档案信息,overallScore/percentile 为 null。

响应

{
  "code": 200,
  "message": "ok",
  "data": {
    "applicationId": 30,
    "jobId": 10,
    "candidateName": "张三",
    "candidateSchool": "清华大学",
    "overallScore": 90.00,
    "percentile": 88.00,
    "cohortSize": 3,
    "dimensionScores": [
      { "dimension": "COMPLIANCE", "score": 100.00, "status": "OK" }
    ]
  }
}

dimensionScores:该候选人最新期快照的各维度(按维度名升序);仅含 dimension / score / status,不暴露 subScores 与内部日志。

6. 企业评分趋势

GET /company/scoring/dashboard/trend?months=6
参数 类型 必填 默认 说明
months int 否 6 统计月数,1–24

months 越界(<1 或 >24)→ 400 / 1001。

  • 岗位评价趋势:按 job_reviews.created_at 年月分组(审核通过评价)求均值。
  • 候选人综合分趋势:读取范围内各期快照,用 overallScoreFromSnapshots 计算每期综合分后求均值(candidateCount 为该期有分候选人数)。
  • 仅返回有数据的月份;avgJobScore/avgCandidateScore 某期无数据时该期缺失(不补 null 空期)。

响应

{
  "code": 200,
  "message": "ok",
  "data": {
    "companyId": 1,
    "months": 6,
    "items": [
      { "period": "2026-08", "avgJobScore": 4.50, "avgCandidateScore": 80.00, "candidateCount": 2 }
    ]
  }
}

7. 全局运营概览(ADMIN)

GET /admin/scoring/dashboard/overview

响应

{
  "code": 200,
  "message": "ok",
  "data": {
    "totalCompanies": 12,
    "totalJobs": 45,
    "totalCandidates": 220,
    "avgCandidateScore": 70.00,
    "topCompanies": [{
      "companyId": 3,
      "companyName": "示例企业",
      "avgCandidateScore": 88.50,
      "jobCount": 5
    }]
  }
}
  • totalCandidates:全平台管线内去重候选人(排除 WITHDRAWN/REJECTED)。
  • avgCandidateScore:全平台有分候选人综合分均值。
  • topCompanies:按候选人综合分均值排序的前 10 家企业。

错误码

复用既有错误码,不新增:

状态码 错误码 说明
400 1001 参数非法(page/size/months 越界)
400 7002 岗位不属于本企业
401 — 未登录(安全过滤器)
403 2002 非 COMPANY/ADMIN 角色、无企业资料
403 8004 投递岗位不属于本企业
404 4001 用户不存在(ADMIN 概览)
404 7001 岗位不存在
404 8002 投递不存在或投递已撤回/被拒

安全说明

  • 全部为 GET 只读;不返回 studentUserId、phone、email、resumeUrl、passwordHash。
  • companyId 一律从 JWT 推导并限定 jobs.company_id,天然隔离企业数据。
  • 候选人排名/趋势不写快照、不触发评分计算,仅读最新期已存在快照。