# 岗位评价与八维评分卡接口说明 > 职来 (mydreamjob) · 岗位评价 + 八维评分卡基础模块 > 基础路径:`/api/v1` · 评价创建/修改/删除需登录;列表/详情/汇总/对比公开 ## 1. 概述 在原岗位评价(rating 1-5 + content + tags)基础上,新增**八个固定维度**的稀疏评分卡: | 维度码 | 说明 | |---|---| | `AUTHENTICITY` | 岗位真实性 | | `BENEFITS` | 基础保障 | | `SALARY_TRANSPARENCY` | 薪资透明 | | `JD_CLARITY` | JD 清晰度 | | `GROWTH` | 成长空间 | | `TEAM_ATMOSPHERE` | 团队氛围 | | `PROMOTION` | 晋升机制 | | `WORK_LIFE_BALANCE` | 工作与生活平衡(含加班强度/工作时间稳定性/弹性办公/休假执行/加班补偿) | - `dimensionScores` **可选**、允许稀疏(可只提交部分维度),每项 1-5 整数; - 未知维度 / 非 1-5 / null 分数 → 400; - 旧客户端不传 `dimensionScores` 完全兼容,不报错; - 同一学生同一岗位只能评价一次 → 409 `DUPLICATE_REVIEW`;越权修改/删除 → 403。 ## 2. 接口 ### 2.1 创建评价 `POST /jobs/{jobId}/reviews` - 仅 STUDENT;企业创建 → 403;重复 → 409。 - 旧字段:`rating`(必填 1-5)、`content`(必填 ≤1000)、`tags`(可选 ≤10)。 - 新增可选 `dimensionScores`(Map,值 1-5): ```json { "rating": 4, "content": "岗位信息真实", "tags": ["团队氛围"], "dimensionScores": { "AUTHENTICITY": 5, "BENEFITS": 4, "SALARY_TRANSPARENCY": 4, "JD_CLARITY": 5, "GROWTH": 4, "TEAM_ATMOSPHERE": 5, "PROMOTION": 3, "WORK_LIFE_BALANCE": 4 } } ``` ### 2.2 评价列表 `GET /jobs/{jobId}/reviews`(公开,分页) 每条返回 `id, jobId, studentUserId, rating, content, tags, status, createdAt, updatedAt, dimensionScores`。 无维度分时 `dimensionScores` 为空对象。 ### 2.3 评价详情 `GET /jobs/{jobId}/reviews/{reviewId}`(公开) 返回单条评价,结构同列表项(含 `dimensionScores`)。 ### 2.4 修改评价 `PUT /jobs/{jobId}/reviews/{reviewId}` - 仅评价本人;他人 → 403;不存在 → 404。 - `dimensionScores` 可选:**只更新请求中实际提交的维度**(已有更新、新增插入);未提交维度保持原值;空对象不删除原有维度。 ### 2.5 删除评价 `DELETE /jobs/{jobId}/reviews/{reviewId}` - 仅评价本人;删除时**级联删除**该评价的维度评分(DB ON DELETE CASCADE),不留下孤儿维度记录。 ### 2.6 评分汇总 `GET /jobs/{jobId}/reviews/summary`(公开) 保留原有 `jobId, totalReviews, averageRating, ratingDistribution, topTags`,新增 `dimensionSummary`: ```json { "dimensionSummary": { "AUTHENTICITY": { "averageScore": 4.5, "sampleCount": 2, "dataState": "INSUFFICIENT" }, "BENEFITS": { "averageScore": 4.0, "sampleCount": 4, "dataState": "SUFFICIENT" } } } ``` - 只统计 `PUBLISHED` 评价中**实际存在**的维度分;不伪造、不补齐; - 始终返回全部 8 个维度; - `sampleCount < 3` → `INSUFFICIENT`;`>= 3` → `SUFFICIENT`;`sampleCount == 0` → `averageScore` 为 null; - `averageScore` 保留 1 位小数,HALF_UP。 ### 2.7 岗位对比 `GET /jobs/compare?ids=1,2,3`(公开,不要求登录) - `ids` 为 2-3 个公开岗位,逗号分隔;少于 2 / 超过 3 / 缺失 / 重复 / 非法 → 400; - 任一岗位不存在或非 PUBLISHED → 404; - 每岗返回:`id, title, city, employmentType, salaryMin, salaryMax, benefits, description, requirements, averageRating, totalReviews, ratingDistribution, tags, dimensionSummary`; - 只返回公开岗位字段与公开评分,**不返回**企业内部字段、联系方式、审核字段或内部备注。 ## 3. 权限 | 操作 | 学生本人 | 其他学生 | 企业 | 未登录 | |---|---|---|---|---| | 创建评价 | ✅ | 403(重复→409) | 403 | 401 | | 修改/删除评价 | ✅ | 403 | 403 | 401 | | 列表/详情/汇总/对比 | 公开 | 公开 | 公开 | ✅ | 身份一律来自 JWT,不信任请求体中的 userId/studentUserId;所有写操作记录 X-Request-Id(超长统一截断为 32 位)。 ## 4. 数据库(V17) `V17__job_review_dimensions.sql`: - 表 `job_review_dimension_scores`:`review_id`(FK→job_reviews ON DELETE CASCADE)、`dimension_code`、`score`(CHECK 1-5)、`created_at/updated_at`; - `UNIQUE(review_id, dimension_code)`(并发唯一性保护)、`INDEX(review_id)`; - **不改** `job_reviews` 表结构,V1-V16 历史迁移不动。 ## 5. Apifox 快速步骤 1. 学生投递可见岗位 → `POST /jobs/{jobId}/reviews` 带 `dimensionScores` → 200。 2. 同一学生重复 `POST` → 409。 3. `GET /jobs/{jobId}/reviews/{reviewId}` → 含 `dimensionScores`。 4. `PUT` 只改 `dimensionScores` 中部分维度 → 其余保持。 5. `GET /jobs/{jobId}/reviews/summary` → 看 `dimensionSummary`(INSUFFICIENT/SUFFICIENT)。 6. `GET /jobs/compare?ids=1,2` → 对比两个公开岗位(不登录)。 7. 企业账号 `POST /jobs/{jobId}/reviews` → 403。 ## 6. 已知限制 1. `benefits` 字段:当前 `jobs` 表无该字段,对比接口返回 `benefits: null` 占位,待产品补充岗位福利后接入。 2. WORK_LIFE_BALANCE 的 5 个子项本轮归并为一个 1-5 分,不拆分存储。 3. 维度分仅学生本人创建评价时可录入;汇总为只读聚合。 4. OpenAPI 快照:`docs/openapi-rc.json` 由 H2 集成测试上下文导出(**56 路径**),现网可用 `GET /api/v1/v3/api-docs` 重新导出。 ## 7. 评价审核与防刷(V18 起) 评价创建经确定性预审(非 AI,详见 `docs/review-moderation-api.md`): - 无风险 → `moderationStatus = AUTO_APPROVED`,同步 200 且公开展示(行为与旧版一致); - 命中规则(敏感词/联系方式/重复模式/高频/批量)→ `moderationStatus = PENDING`,保存成功但不公开, 作者响应含 `moderationStatus` 与安全原因码(不含敏感词原文); - 公开列表/详情/汇总仅返回 `AUTO_APPROVED` 与 `APPROVED` 的评价; - 管理员通过 `POST /admin/reviews/{reviewId}/decision` 审核(`APPROVED` 公开 / `REJECTED` 永不公开), 重复审核返回 409 `REVIEW_ALREADY_DECIDED`;待审列表与历史见 `GET /admin/reviews/pending`、`GET /admin/reviews/history`。 评价视图统一增加 `moderationStatus` 字段。