# 企业回复评价功能接口说明 > 职来 (mydreamjob) · 企业回复评价模块 > 基础路径:`/api/v1` · 企业侧回复接口需岗位所属企业;管理端接口仅 ADMIN ## 1. 概述 在"学生评价岗位"基础上,新增**企业对岗位评价的官方回复**,并由管理员审核后对外展示: - 一条公开评价**只能回复一次**(`review_id` 唯一); - 回复创建即 `moderationStatus = PENDING`,**不对外展示**,需管理员审核; - 管理员 `APPROVED` → 公开可见;`REJECTED` → 永不公开; - 公开查询只返回 `moderationStatus = APPROVED` 的回复; - 回复所属企业可以随时查看自己回复的任意状态(审核中/已批准/被驳回),并在被驳回时知晓原因。 审核状态值:`PENDING`(待审) / `APPROVED`(已批准公开) / `REJECTED`(已驳回)。 ## 2. 可见性规则 | 请求方 | PENDING | APPROVED | REJECTED | |---|---|---|---| | 回复所属企业(本人) | ✅ 可见 | ✅ 可见 | ✅ 可见(含 `moderationReason`) | | 其他登录用户 / 匿名 | 视为不存在(9108) | ✅ 可见 | 视为不存在(9108) | > 匿名访问由 Spring Security 的匿名 token 表示,系统将其视为"非本人",只返回 `APPROVED`。 ## 3. 企业侧回复接口 ### 3.1 创建回复 `POST /reviews/{reviewId}/reply` 请求体: ```json { "content": "感谢您的反馈,我们会持续改进。" } ``` - `content` 必填,≤500 字; - 仅岗位所属企业可回复;评价不存在或未公开 → `REVIEW_NOT_FOUND`;非所属企业 → `FORBIDDEN`; - 该评价已有回复 → `DUPLICATE_REPLY`(一条评价仅一条回复); - 创建成功返回 `PENDING`,**不对外展示**。 ### 3.2 查询回复 `GET /reviews/{reviewId}/reply` - 公开接口;按"可见性规则"返回; - 本人可见任意状态;其他人/匿名仅见 `APPROVED`,否则 `REPLY_NOT_FOUND`。 ### 3.3 更新回复 `PUT /reviews/{reviewId}/reply` 请求体: ```json { "content": "感谢您的反馈,我们已优化面试流程。" } ``` - `content` ≤500 字; - 仅回复所属企业可改(非所属 → `FORBIDDEN`);回复不存在 → `REPLY_NOT_FOUND`; - 更新后 `moderationStatus` **重置为 PENDING**,需重新审核。 ### 3.4 删除回复 `DELETE /reviews/{reviewId}/reply` - 仅回复所属企业;回复不存在 → `REPLY_NOT_FOUND`; - 返回 `{ "message": "reply deleted" }`。 ## 4. 管理端回复接口(仅 ADMIN) ### 4.1 待审/回复列表 `GET /admin/reviews/replies/pending` - 仅 ADMIN(非 ADMIN → 403/`FORBIDDEN`,未登录 → 401/`UNAUTHORIZED`);分页; - 可选筛选(均可不传,有默认):`companyId`(企业)、`jobId`(岗位)、`moderationStatus`(**默认 `PENDING`**)、`createdFrom`、`createdTo`、`page`(0)、`size`(20); - `moderationStatus ∈ {PENDING, APPROVED, REJECTED}`,非法值 → `BAD_REQUEST`;`size` 超限(>100)或 `page<0` → `BAD_REQUEST`; - 返回 `PageResponse`:`items[] / total / page / size / totalPages`; - 每条含回复字段(`id, reviewId, companyUserId, content, moderationStatus, moderationReason, createdAt, updatedAt, moderationUpdatedAt`)+ 上下文补全(`jobId, jobTitle, companyId, companyName, reviewRating, reviewContent, studentUserId`); - `moderationStatus` 缺省为 `PENDING`,要查所有/已批准/驳回,显式传该参数即可。 ### 4.2 审核决策 `POST /admin/reviews/replies/{replyId}/decision` 请求体: ```json { "decision": "APPROVED", "reason": "内容合规,同意公开" } ``` - `decision` 必填,`APPROVED` 或 `REJECTED`;`reason` 可选 ≤500 字(写入 `moderationReason`); - 仅 ADMIN;仅 `PENDING` 可审,已审核重复提交 → `REPLY_ALREADY_DECIDED`; - `APPROVED` → 公开可见;`REJECTED` → 永不公开;审核人来自 JWT; - 返回审核后回复视图。 ## 5. 权限一览 | 操作 | ADMIN | 岗位所属企业 | 其他企业/学生 | 未登录 | |---|---|---|---|---| | 创建/更新/删除回复 | — | ✅ | 403 | 401 | | 查询回复(本人) | — | ✅ 任意状态 | — | — | | 查询回复(公开) | ✅ (仅 APPROVED) | ✅ (仅 APPROVED) | ✅ (仅 APPROVED) | ✅ (仅 APPROVED) | | 待审列表/审核决策 | ✅ | 403 | 403 | 401 | 企业/审核者身份一律来自 JWT,不信任请求体 userId。 ## 6. 数据库(V34) `V34__company_review_replies.sql` 新增表 `company_review_replies`: | 字段 | 说明 | |---|---| | `id` | 主键,自增 | | `review_id` | 被回复的评价 id,**唯一**,一条评价一条回复 | | `company_user_id` | 回复企业账号 id | | `content` | 回复内容 | | `moderation_status` | 默认 `PENDING`;`PENDING/APPROVED/REJECTED` | | `moderation_reason` | 审核原因/意见 | | `moderation_updated_at` | 审核时间 | | `created_at` / `updated_at` | 创建/更新时间 | - 管理端筛选通过 `reply → review → job → company` 关联实现,不加额外字段; - 不改既有表结构,历史迁移不动。 ## 7. 错误码 | 码 | 场景 | |---|---| | 2001 | `UNAUTHORIZED` 未登录 | | 2002 | `FORBIDDEN` 非 ADMIN / 非所属企业 | | 1001 | `BAD_REQUEST` 参数非法(decision、分页越界、状态非法等) | | 9102 | `REVIEW_NOT_FOUND` 评价不存在或未公开 | | 9107 | `DUPLICATE_REPLY` 该评价已有回复 | | 9108 | `REPLY_NOT_FOUND` 回复不存在/非本人查询非 APPROVED 回复 | | 9109 | `REPLY_ALREADY_DECIDED` 该回复已审核过 | ## 8. 测试 覆盖:创建回复 PENDING 且不公开、非所属企业 403、重复回复 9107、所有者可见任意状态、匿名/他人仅见 APPROVED、更新后重置 PENDING、删除后查询 9108、管理员列表默认 PENDING 且筛选正确(企业/岗位/状态/时间/分页/非法值)、决策仅 ADMIN、仅 PENDING 可审重复 9109、非 ADMIN 调管理接口 403、视图上下文补全。 ## 9. 已知限制 1. 回复不可多次审核;如需调整,企业先更新内容(重置为 PENDING)再重新走审核。 2. 一条评价仅一条企业回复(当前设计)。 3. 管理端列表接口与既有评价审核接口共用 `/admin/reviews` 前缀,路径区分节点(/replies/*)。