Browse Source

docs: 归档联调路径校正映射与更新问题清单状态

- 后端联调前端实现.md §3 按 OpenAPI 校正结果重标已落地真实端点
- 接口联调问题清单.md 新增『零、进展更新』:89 函数分类(ALIGNED 6/WRONG→REAL 14/PHANTOM 69)、P0-1/P0-2/P1-1 标记已解决
- 新增 docs/联调路径校正映射.md 逐函数权威表
- 新增 P2-2 风险:真实分页信封为 {items} 而非 mock 的 {content}
master
doublex001 4 weeks ago
parent
commit
86c543c3d7
  1. 109
      docs/联调路径校正映射.md
  2. 53
      后端联调前端实现.md
  3. 125
      接口联调问题清单.md
  4. BIN
      职来后端接口联调说明.docx

109
docs/联调路径校正映射.md

@ -0,0 +1,109 @@
# 联调路径校正映射表(基于 job.youthome.com.cn OpenAPI 实测)
> 生成日期:2026-09-28 | 数据源:`scripts/openapi.json`(182 条真实路径 / 220 path-methods)
> 审计范围:api.ts 内全部 `request()` 调用(89 个函数)
> 结论:ALIGNED(已对齐)= 6,WRONG→REAL(路径错但有真实等价)= 14,PHANTOM(幽灵域,后端无契约)= 69
## 一、已对齐(无需改路径)
| 函数 | 真实路径 | 原标记 |
|---|---|---|
| `createJobReview` | `POST /jobs/{jobId}/reviews` | 已校正 |
| `fetchCompareData` | `/jobs/compare` | 已校正 |
| `fetchEmployeeReviews` | `GET /jobs/{jobId}/reviews` | 已校正 |
| `fetchJobDetail` | `GET /jobs/{jobId}` | 已校正 |
| `fetchOfferCompareData` | `GET /offers/compare` | 【待确认】 |
| `fetchUserProfile` | `GET /profile/me` | 已校正 |
## 二、路径错但有真实等价端点(需改路径)
| 函数 | 当前(错) | 应改为(真实) | 说明 |
|---|---|---|---|
| `fetchCandidateDetail` | `/enterprise/candidates/${candidateId}` | `/company/candidates/{applicationId}` | 前端猜 /enterprise/candidates,真路径在 /company 域 |
| `fetchConversation` | `/chat/conversations/${id}` | `GET /conversations/{id}` | 前端猜 /chat/conversations,真路径 /conversations/{id} |
| `fetchConversations` | `/messages/conversations` | `GET /conversations` | 前端猜 /messages/conversations,真 /conversations |
| `fetchInterviewScore` | `/enterprise/interviews/${interviewId}/score` | `GET /interviews/{interviewId}/score` | 前端猜 /enterprise/interviews,真路径在 /interviews 域 |
| `fetchInterviewScoreDraft` | `/enterprise/interviews/${interviewId}/score/draft` | `PUT /interviews/{interviewId}/score` | 真路径无 /draft 子路径,保存草稿用 PUT /interviews/{id}/score |
| `fetchInterviews` | `/messages/interviews` | `GET /interviews/me` | 前端猜 /messages/interviews,真 /interviews/me(我的面试列表) |
| `fetchJobPreference` | `/profile/me/job-preference` | `GET/PUT /profile/me/preferences` | 前端猜 /profile/me/job-preference,真路径 /profile/me/preferences |
| `fetchJobProgress` | `/tools/job-progress` | `GET /profile/me/career-progress` | 前端猜 /tools/job-progress,真 /profile/me/career-progress(统一求职进度聚合) |
| `fetchMatchResult` | `/messages/match-result` | `GET /applications/{id}/match 或 /jobs/{jobId}/match` | 前端猜 /messages/match-result,真为投递/岗位匹配诊断 |
| `fetchNotifications` | `/messages/notifications` | `GET /notifications` | 前端猜 /messages/notifications,真 /notifications |
| `fetchRankData` | `/jobs/rank` | `GET /jobs/{jobId}/competition-ranking` | 前端猜 /jobs/rank,真为按岗位竞争力排名,语义不同(需 jobId) |
| `fetchResume` | `/resume` | `GET /profile/me/resume` | 前端猜 /resume,真 /profile/me/resume(下载简历) |
| `saveJobPreference` | `/profile/me/job-preference` | `PUT /profile/me/preferences` | 同上 |
| `saveResumeBasicInfo` | `/resume/basic-info` | `POST /profile/me/resume (multipart)` | 前端猜 /resume/basic-info,真为上传简历文件(multipart),结构化字段在 PUT /profile/me |
## 三、幽灵域(后端 OpenAPI 无契约,必须退回 mock-only)
| 函数 | 当前(幽灵)路径 | 说明 |
|---|---|---|
| `deleteSalaryRecord` | `/salary/records/${id}` | 无 /salary 域,后端未提供 |
| `fetchAIInterviewData` | `/interview/config` | 未命中 OpenAPI |
| `fetchAITools` | `/growth/ai-tools` | 未命中 OpenAPI |
| `fetchAbilityAssessment` | `/growth/ability` | 未命中 OpenAPI |
| `fetchAboutInfo` | `/settings/about` | 未命中 OpenAPI |
| `fetchAccountCancel` | `/settings/account-cancel` | 未命中 OpenAPI |
| `fetchAccountSecurity` | `/settings/account-security` | 未命中 OpenAPI |
| `fetchAppealForm` | `/evaluation/appeal` | 未命中 OpenAPI |
| `fetchArticles` | `/growth/articles` | 未命中 OpenAPI |
| `fetchAuditReport` | `/operation/audit-report` | 未命中 OpenAPI |
| `fetchBadges` | `/user/badges` | 未命中 OpenAPI |
| `fetchDimensionScores` | `/user/dimension-scores` | 未命中 OpenAPI |
| `fetchDndSetting` | `/settings/privacy/dnd` | 未命中 OpenAPI |
| `fetchEnterpriseCertification` | `/enterprise/certification` | 未命中 OpenAPI |
| `fetchEnterpriseCommunication` | `/enterprise/communication` | 未命中 OpenAPI |
| `fetchEnterpriseEntry` | `/user/enterprise-entry` | 未命中 OpenAPI |
| `fetchEnterpriseOverview` | `/enterprise/overview` | 未命中 OpenAPI |
| `fetchGameLevels` | `/game/levels` | 未命中 OpenAPI |
| `fetchGameProgress` | `/game/progress` | 未命中 OpenAPI |
| `fetchHREvaluation` | `/evaluation/hr` | 未命中 OpenAPI |
| `fetchHollandAssessment` | `/growth/holland` | 未命中 OpenAPI |
| `fetchHollandIntro` | `/growth/holland-intro` | 未命中 OpenAPI |
| `fetchIdentityOptions` | `/tools/identity-options` | 未命中 OpenAPI |
| `fetchJobEvaluationEmptyState` | `/enterprise/job-evaluation-empty` | 未命中 OpenAPI |
| `fetchJobEvaluationManagement` | `/enterprise/job-evaluations` | 未命中 OpenAPI |
| `fetchJobManagement` | `/enterprise/job-management` | 未命中 OpenAPI |
| `fetchJobOverallScore` | `/jobs/${id}/score` | 无 /jobs/{id}/score,综合分见 /jobs/{id}/competition-ranking 或 /profile/me/candidate-scoring |
| `fetchJobPublishForm` | `/enterprise/jobs/publish-form` | 未命中 OpenAPI |
| `fetchKeywordBlock` | `/settings/privacy/keywords` | 未命中 OpenAPI |
| `fetchLegalBrand` | `/legal/brand` | 未命中 OpenAPI |
| `fetchLegalConversation` | `/legal/conversations/default` | 未命中 OpenAPI |
| `fetchLegalDocument` | `/settings/legal-document/${id}` | 无 /legal 域,后端未提供 |
| `fetchLegalFAQs` | `/legal/faqs` | 未命中 OpenAPI |
| `fetchLegalMembership` | `/legal/membership` | 未命中 OpenAPI |
| `fetchLegalOrders` | `/legal/orders` | 未命中 OpenAPI |
| `fetchLegalPlans` | `/legal/plans` | 未命中 OpenAPI |
| `fetchLegalServiceRequests` | `/legal/service-requests` | 未命中 OpenAPI |
| `fetchLegalServices` | `/legal/services` | 未命中 OpenAPI |
| `fetchLegalTemplates` | `/legal/templates` | 未命中 OpenAPI |
| `fetchMenuItems` | `/user/menus` | 未命中 OpenAPI |
| `fetchNotificationSettings` | `/settings/notification` | 未命中 OpenAPI |
| `fetchOperationRules` | `/operation/rules` | 未命中 OpenAPI |
| `fetchOverallScore` | `/user/overall-score` | 未命中 OpenAPI |
| `fetchPendingOfferCount` | `/offers/pending/count` | 无 /offers/pending/count,可用 /offers/statistics 替代(需确认) |
| `fetchPersonalDataExport` | `/settings/personal-data-export` | 未命中 OpenAPI |
| `fetchPrivacyCenter` | `/settings/privacy-center` | 未命中 OpenAPI |
| `fetchPrivacyDetailSetting` | `/settings/privacy/${id}` | 无 /settings 域,后端未提供 |
| `fetchPrivacySettings` | `/settings/privacy` | 未命中 OpenAPI |
| `fetchQualifications` | `/settings/qualifications` | 未命中 OpenAPI |
| `fetchResumeExportSettings` | `/resume/export-settings` | 无 /resume/export-settings,导出设置本地维护 |
| `fetchResumeSavedAt` | `/resume/saved-at` | 无 /resume/saved-at,简历保存时间可由 /profile/me/resume-versions 派生 |
| `fetchSalaryBrackets` | `/tools/salary-brackets` | 未命中 OpenAPI |
| `fetchSalaryData` | `/jobs/${id}/salary` | 无 /jobs/{id}/salary,后端未提供薪资明细端点 |
| `fetchSalaryRecords` | `/salary/records` | 未命中 OpenAPI |
| `fetchSalaryToolLinks` | `/tools/salary-related` | 未命中 OpenAPI |
| `fetchSkillCloud` | `/tools/skill-cloud` | 未命中 OpenAPI |
| `fetchSkillLearningPath` | `/tools/skill-learning-path` | 未命中 OpenAPI |
| `fetchTalentRecommendation` | `/enterprise/talent-recommendation` | 未命中 OpenAPI |
| `fetchUserStats` | `/user/stats` | 未命中 OpenAPI |
| `fetchWeightSettings` | `/jobs/weight-settings` | 无 /jobs/weight-settings,权重见 /profile/me/review-weights、/review-weight-templates |
| `saveResumeEducation` | `/resume/education` | 无 /resume/education,简历整体由 /profile/me/resume + resume-versions 管理 |
| `saveResumeExperience` | `/resume/experience` | 同上 |
| `saveResumeExportSettings` | `/resume/export-settings` | 未命中 OpenAPI |
| `saveResumeProjects` | `/resume/projects` | 同上 |
| `saveResumeSelfEvaluation` | `/resume/self-evaluation` | 同上 |
| `saveResumeSkills` | `/resume/skills` | 同上 |
| `saveResumeSnapshot` | `/resume/save` | 同上 |
| `saveSalaryRecord` | `/salary/records` | 无 /salary/records |
| `saveWeightSettings` | `/weight-settings` | 无 /weight-settings |

53
后端联调前端实现.md

@ -34,36 +34,53 @@
| §8 状态码语义 | `pickHttpMessage` 覆盖 400/401/403/404/409/429/500/503;网络异常降级为 `httpStatus=0` | | §8 状态码语义 | `pickHttpMessage` 覆盖 400/401/403/404/409/429/500/503;网络异常降级为 `httpStatus=0` |
| §10 安全 | 不写 Token/验证码/密码到日志或前端 DOM;`X-Request-Id` 用于联调报障 | | §10 安全 | 不写 Token/验证码/密码到日志或前端 DOM;`X-Request-Id` 用于联调报障 |
## 三、业务端点转换进度(mock 开关 + 岗位域) ## 三、业务端点转换进度(mock 开关 + 全量 fetch 函数,2026-09-24 收口)
> 转换规则:保留函数签名与返回类型 `T`(即 AGENTS.md「保留签名、只换函数体」),`if (isMockMode())` 分支保留本地数据,真实分支走 `request<T>(path, { auth, query })`。路径按规范 §7 重映射(旧 `@url` 多带 `/api` 前缀、未带 `/v1`,已校正)。 > 转换规则:保留函数签名与返回类型 `T`(即 AGENTS.md「保留签名、只换函数体」),`if (isMockMode())` 分支保留本地数据,真实分支走 `request<T>(path, { auth, query })`。路径按规范 §7 重映射(旧 `@url` 多带 `/api` 前缀、未带 `/v1`,已校正)。
### 3.1 已完成(岗位域 · 候选侧读取) ### 3.1 已落地真实端点(2026-09-28 经 OpenAPI 校正)
| 函数 | mock 分支 | 真实路径(§7) | 鉴权 | 说明 | > 路径以 `docs/联调路径校正映射.md` 为权威逐函数表;下表仅列本次确认可直连的端点(ALIGNED + WRONG→REAL)。
|---|---|---|---|---|
| `fetchJobList` | 本地筛选/排序/分页 | `GET /jobs` | 否 | query 映射:`pageSize→size`;数组多选逗号拼接;`keyword/industry/city/education` 等空值跳过 |
| `fetchJobDetail` | 本地详情 | `GET /jobs/{id}` | 否 | 公开岗位详情 |
| `fetchJobOverallScore` | 本地八维缩放 | `GET /jobs/{id}/score` | 否 | 综合评分;响应结构以 OpenAPI 为准 |
| `fetchJobPreference` | `resolveJobPreference()` 派生 | `GET /profile/me/job-preference` | 是 | 求职者偏好(§5 STUDENT 前缀) |
| `fetchFavorites` | 本地收藏子集 | `GET /profile/me/favorites` | 是 | 当前用户收藏 |
| `fetchJobProgress` | 本地进度 | `GET /tools/job-progress` | 否 | 求职进度工具数据 |
> 鉴权列「是」= 默认带 Bearer;「否」= `auth:false` 匿名读取(§7 公开岗位)。 | 函数 | 真实路径 | 鉴权 | 说明 |
|---|---|---|---|
| `fetchJobList` | `GET /jobs` | 否 | 分页信封 `{items}` |
| `fetchJobDetail` | `GET /jobs/{id}` | 否 | 公开岗位详情 |
| `fetchJobPreference` | `GET /profile/me/preferences` | 是 | 原 `/profile/me/job-preference` 已校正 |
| `fetchFavorites` | `GET /jobs/favorites` | 是 | 原 `/profile/me/favorites` 已校正 |
| `fetchJobProgress` | `GET /profile/me/career-progress` | 否 | 原 `/tools/job-progress` 已校正 |
| `fetchEmployeeReviews` | `GET /jobs/{id}/reviews` | 否 | |
| `createJobReview` | `POST /jobs/{id}/reviews` | 是 | body `{content}` |
| `fetchCompareData` | `GET /jobs/compare` | 否 | |
| `fetchUserProfile` | `GET /profile/me` | 是 | |
| `fetchResume` | `GET /profile/me/resume` | 是 | 原 `/resume` 已校正(修复双前缀 bug) |
| `fetchConversations` | `GET /conversations` | 是 | 原 `/messages/conversations` 已校正 |
| `fetchNotifications` | `GET /notifications` | 是 | 原 `/messages/notifications` 已校正 |
| `fetchInterviews` | `GET /interviews/me` | 是 | 原 `/messages/interviews` 已校正 |
| `fetchConversation` | `GET /conversations/{id}` | 是 | 原 `/chat/conversations/{id}` 已校正 |
| `fetchRankData` | `GET /jobs/{jobId}/competition-ranking` | 否 | 原 `/jobs/rank` 已校正(修复 `${jobId}` 未插值 bug) |
| `fetchCandidateDetail` | `GET /company/candidates/{applicationId}` | 是 | 原 `/enterprise/candidates` 已校正 |
| `fetchInterviewScore` | `GET /interviews/{id}/score` | 是 | 原 `/enterprise/interviews` 已校正 |
| `fetchInterviewScoreDraft` | `PUT /interviews/{id}/score` | 是 | 草稿复用评分端点,原 `/enterprise/.../draft` 已校正 |
| `fetchOfferCompareData` | `GET /offers/compare` | 否 | 已对齐 |
### 3.2 待转(下一阶段,按业务域分批) > 写函数 `saveJobPreference`(PUT /profile/me/preferences)已校正路径;其余 `saveResume*` / `saveWeightSettings` / `saveSalaryRecord` 等经审计属「幽灵域」(后端无 OpenAPI 契约),已退回 mock-only。
- **岗位详情子资源**:`fetchSalaryData` / `fetchEmployeeReviews` / `createJobReview` / `fetchCompareData`(仍处于 `/api/jobs/:id/...` 旧路径,需校正)。 ### 3.1.2 幽灵域(本轮批量转换的其余 62 个 fetch 函数,2026-09-28 校正)
- **企业端岗位**:`fetchJobManagement` / `fetchJobPublishForm` / `fetchJobEvaluationManagement` / `fetchJobEvaluationEmptyState`(§7 未列,需 OpenAPI 确认前缀)。
- **简历 / 资料**:`fetchResume` / `fetchUserProfile` / `fetchProfileXxx`(STUDENT 前缀)。
- **消息 / 沟通**:`fetchConversations` / `fetchNotifications` / `fetchMessages`(§7 未列)。
- **其余公开读取**:`fetchJobFilters` / `fetchJobSearch` 等若后端拆成独立端点,需补映射。
## 四、明确未做(下一阶段) > 经 OpenAPI 审计,这 62 个函数所属域(/growth、/user、/tools、/game、/interview、/evaluation、/enterprise、/legal、/settings、/salary、/operation 等)**后端均无契约**。处理方式:保留 `if(isMockMode())` mock 分支,**真实态不再调用 `request()`(翻真实开关也不触网)**,待后端补齐契约后再接。原占位 `【待确认】` 标记已全部清除。逐函数明细见 `docs/联调路径校正映射.md` §三。
### 3.2 待转 / 明确不接后端
- **设备本地能力(保持 mock,无后端等价物)**:`fetchCacheSize`(存储占用)、`fetchCarrierPhone`(运营商取号 SDK)、`fetchWechatLoginResult`(微信登录态)、`fetchOnboardingProfile`(本地引导资料唯一真相源)、`fetchOnboardingChecklist`(本地清单派生)、`fetchDeleteAllData`(本地清空)。
- **非 fetch 写函数(不在本次 fetch 范围,后续接)**:`sendChatMessage`、`saveResume*` 系列、`saveOnboardingProfile`、`toggleFavorite`、`saveJobPreference` 等写操作——需 PUT/POST body 映射 + 保留本地 storage 回退作为真实后端未就绪时的兜底。
## 四、明确未做(写入类 + 实时能力,下一阶段)
- **WebSocket**:`wss://job.youthome.com.cn/api/v1/ws` 未接入(无对应实时功能)。 - **WebSocket**:`wss://job.youthome.com.cn/api/v1/ws` 未接入(无对应实时功能)。
- **企业入驻状态机**:`/companies/me/onboarding` 的 `missingFields` / `allowedActions` 驱动 UI 尚未接。 - **企业入驻状态机**:`/companies/me/onboarding` 的 `missingFields` / `allowedActions` 驱动 UI 尚未接。
- **其余入口页角色纠正**:仅密码登录页已接 `/auth/me`;微信登录、验证码登录等入口需在登录后补齐角色权威化。 - **其余入口页角色纠正**:仅密码登录页已接 `/auth/me`;微信登录、验证码登录等入口需在登录后补齐角色权威化。
- **写入类函数**:见 §3.2 非 fetch 写函数(sendChatMessage / saveResume* / saveOnboardingProfile / toggleFavorite / saveJobPreference 等),需补 body 映射与本地 storage 兜底。
## 五、命名待确认(非阻塞) ## 五、命名待确认(非阻塞)

125
接口联调问题清单.md

@ -0,0 +1,125 @@
# 职来(有职)前端 · 已转换接口(已"调过")存在的问题
> 生成日期:2026-09-28
> 范围界定:**本文只讨论已在代码中实现真实分支(即已转换为直连后端、存在 `request()` 调用)的接口**存在的问题。
> 不纳入:纯 mock 接口(`sendChatMessage`、`loginByPhone`、`saveOnboardingProfile`、`fetchOnboardingProfile`、设备本地能力 `fetchCacheSize` / `clearAppCache` / `fetchCarrierPhone` / `fetchWechatLoginResult` 等);明确尚未启动的 WebSocket、企业入驻状态机。
> 说明:地基(统一请求层、双 Token、401 刷新、角色映射、健康检查)实现正确,不在本文问题范围内。
---
## 零、进展更新(2026-09-28 经 OpenAPI 实机校正)
> 本轮以 `https://job.youthome.com.cn/api/v1/v3/api-docs`(OpenAPI 3.1.0,182 路径 / 220 path-method)为唯一准绳,对 `api.ts` 全部 `request()` 函数做了实机验证(测试号 `19900009021` 登录取 token 后逐一打真实路径,路径返回业务错误码 6001/7001/8002/8305 等即视为「路径存在、契约待对齐」,网关 404 视为「路径不存在」)。
### 审计结论(89 个 request 函数)
- **ALIGNED(6)**:路径与 OpenAPI 完全一致,翻开关即直连。
- **WRONG→REAL(14)**:路径前端猜错但有真实等价端点,已改路径(例:`/messages/conversations`→`/conversations`、`/resume`→`/profile/me/resume`、`/jobs/rank`→`/jobs/{id}/competition-ranking`、`/enterprise/candidates`→`/company/candidates`、`/enterprise/interviews`→`/interviews`)。
- **PHANTOM(69)**:所属域后端无 OpenAPI 契约,翻开关必 404。已**退回 mock-only**(真实态不再调用 `request`,翻真实开关也不触网),待后端补齐契约再接。
### 标记清理
- `【待确认】` 标记:**0 处**(全部清除,含 `【待确认:…】` 形式)。
- 实机验证:ALIGNED + WRONG→REAL 共 ~20 个接口真实路径均返回业务错误码(非网关 404),证明路径正确。
### 问题状态总览
| 原编号 | 状态 | 说明 |
|---|---|---|
| P0-1 | ✅ 已解决 | 89 函数已按 OpenAPI 校正并分类(ALIGNED 6 / WRONG→REAL 14 / PHANTOM 69) |
| P0-2 | ✅ 已解决 | 4 个桥接测试改为断言真实路径;幽灵域真实态断言已删 |
| P1-1 | ✅ 已解决 | `后端联调前端实现.md` §3 已按代码现状重标 |
| P1-2 | ⏳ 待办 | Token `expiresIn` 仍未处理(见下「遗留 P1-2」) |
| P1-3 | ⏳ 待办 | `/auth/me` 角色权威化仍仅在密码登录入口 |
| P1-4 | 🔶 部分 | 幽灵域写函数已退回 mock;已对齐写函数 body 形态待统一 |
| P2-1 | ⏳ 待办 | 145 处 JSDoc `@url /api` 旧前缀未清 |
| P2-2 | ⚠️ 新增风险 | 真实分页信封为 `{items}` 而非前端 mock 的 `{content}` |
| P2-3 | ⏳ 待办 | 双真相源切换策略未定 |
| P2-4 | ✅ 缓解 | 默认仍 mock;现幽灵域翻开关也不触网 |
### 遗留 P1-2(Token 有效期)
后端登录返回 `expiresIn`(秒数)而非 `expiresAt`;前端 `AuthContext` 仍用 `TOKEN_TTL_MS` 兜底成假 TTL。本轮未改,需单独排期修。
### 新增 P2-2 风险(分页信封差异)
前端 mock 分页返回 `{content}`,真实后端返回 `{items}`(Spring Data 分页信封)。若 Hook 按 `.content` 取数,翻真实态会渲染空列表。需数据层对齐:**统一读 `items`**,mock 层返回结构向 `{items}` 收敛或 Hook 做兼容。
---
## 一、结论
- 已转换接口在代码层面"连接"基本铺完:`api.ts` 内 85 个 `fetch*` 读函数 + 大量 `save*/submit*/update*` 写函数**都已带有真实分支**(`if (!isMockMode()) return request(...)`),且全部受 `isMockMode()` 保护,默认 mock 态不会误触网。
- **但契约未经后端校验**:全文件 **65 处 `【待确认】`** 标记真实路径为前端推测;**157 处 JSDoc `@url` 仍写旧 `/api` 前缀**(实际 `request()` 已去 `/api`,两者不一致)。
- **现有测试锁定的是推测路径而非真实契约**,制造"绿灯已通过"的错觉。
- **文档与代码脱节**:`后端联调前端实现.md` §3.2 把已转换的 `saveResume*`、`saveJobPreference` 标为"未接后端 / 后续接",与代码现状不符。
> 一句话:**这些接口"代码连了、契约没对"。** 当前不能宣布"已联调完成"。
---
## 二、问题清单(仅已转换接口)
### P0 — 翻开关即爆
| # | 问题 | 证据 | 影响 |
|---|---|---|---|
| P0-1 | **【已解决 2026-09-28】** 原 65 个已转换接口真实路径为前端猜测(`【待确认】`),未对照 OpenAPI 校正 | 现 `【待确认】` 0 处;89 函数已分类 ALIGNED 6 / WRONG→REAL 14 / PHANTOM 69 | 翻开关后 ALIGNED+WRONG→REAL 共 ~20 接口直连真实后端(返回业务码非 404);PHANTOM 69 已退回 mock-only 不触网 |
| P0-2 | **【已解决 2026-09-28】** 测试锁定的是推测路径,不是真实契约 | `backend-bridge-remaining.test.ts` 等 4 文件已改为断言经 OpenAPI 确认的真实路径;幽灵域真实态断言已删除 | CI 绿灯现对应真实契约;81/81 桥接测试通过 |
### P1 — 必须修,否则已转换接口不可信
| # | 问题 | 证据 | 影响 |
|---|---|---|---|
| P1-1 | **文档与代码脱节**:已转换的 `saveResume*`、`saveJobPreference` 被误标"未接后端" | 代码 3352/3369/3387/3413/3426/3439/3459/8684 等均有 `request(...)` 真实分支 | 状态失真,排期与验收失去依据 |
| P1-2 | **Token 有效期由前端臆造**:后端不返回 `expiresAt` 时,`AuthContext` 用 `TOKEN_TTL_MS` 兜底成假 7 天 TTL | `token-store.ts` 注释"后端可能不返回,故可选";`AuthContext.tsx:161/173` `expiresAt ?? Date.now()+TOKEN_TTL_MS`;`isTokenValid` 据此判断 | 影响所有已转换的鉴权请求:后端短过期时前端以为有效、长期不主动刷新,只能靠 401 兜底;或前端假 TTL 过期后误判登出 |
| P1-3 | **角色权威化接口 `/auth/me` 已转换,但只在密码登录入口调用** | 仅 `P2PasswordLogin.tsx:53` 调 `fetchCurrentUser`;微信登录 / 验证码登录 / 注册完成(`useRegisterFinish`)均用本地角色,不调 `/auth/me` | 多入口登录后角色可能与后端不一致,路由纠正逻辑仅在密码入口生效 |
| P1-4 | **已转换写接口 body 形态不一致**:有的包 `{skills}`、有的裸传 `items`、有的包 `{items}` | `saveResumeSkills` → `{ skills }`(3387);`saveResumeExperience` → `items`(3426,未包裹);`saveResumeEducation` → `{ items }`(3413) | 后端若要求统一 envelope,部分已转换写接口会 400 / 字段丢失 |
### P2 — 隐患 / 卫生
| # | 问题 | 证据 | 影响 |
|---|---|---|---|
| P2-1 | **157 处 JSDoc `@url` 仍写旧 `/api` 前缀**,与实际 `request()` 路径(已去 `/api`)不一致 | `grep @url /api` = 157;实际 `request('/jobs')` 无 `/api` | 维护者按注释拼地址必错;JSDoc 不能作契约依据 |
| P2-2 | **【新增风险 2026-09-28】查询 / 分页参数映射是前端假设;且真实分页信封为 `{items}` 非前端 mock 的 `{content}`** | `http.ts` `buildQuery` + `fetchJobList` 注释;实机验证 `/jobs` 等列表返回 `{total,size,totalPages,page,items}` | 后端若用不同命名 / 分页模型,已转换读接口静默返回全量或错页;**Hook 若按 `.content` 取数,翻真实态会渲染空列表**(需数据层统一读 `items`) |
| P2-3 | **mock / 真实双真相源切换一致性**:mock 态 `saveResumeSnapshot` 写本地 storage 覆盖层、`fetchResume` 读本地;真实态写后端、读后端 | `saveResumeSnapshot`(mock 写 storage) vs `fetchResume`(真实读后端) | 同一设备从 mock 翻真实后,本地已填资料不出现在后端返回中,需明确迁移/清空策略 |
| P2-4 | **`apiUseMock` 默认 `true` 的隐患**:容易被误判为"联调完成"而翻开关 | `http.ts:31` 默认 `true` | 翻开关即触发 P0-1 的 65 个错误请求 |
---
## 三、逐域未确认路径明细(P0-1 附录)
> 下列域的已转换接口真实路径均带 `【待确认】`,为前端推测,未经 OpenAPI 校正。
| 域 | 代表函数 | 推测路径 |
|---|---|---|
| 简历写 / 读 | `saveResumeBasicInfo` / `fetchResume` | `/resume/*`、`/resume/save` |
| 消息 / 沟通 | `fetchConversations` / `fetchConversation` / `fetchMatchResult` | `/messages/*`、`/chat/conversations/{id}` |
| 求职者资料 / 偏好 | `fetchUserProfile` / `saveJobPreference` | `/profile/me`、`/profile/me/job-preference` |
| 薪资 / 工具 | `fetchSalaryRecords` / `fetchWeightSettings` | `/salary/records`、`/jobs/weight-settings`、`/tools/*` |
| 测评 / 成长 | `fetchHollandAssessment` / `fetchSkillCloud` | `/growth/*`、`/user/*`、`/tools/*`、`/game/*` |
| 企业端 | `fetchJobManagement` / `fetchEnterpriseOverview` | `/enterprise/*` |
| 法律(阿布阿诺) | `fetchLegalBrand` / `fetchLegalOrders` | `/legal/*` |
| 隐私 / 设置 / 账户 | `fetchPrivacySettings` / `fetchAccountCancel` | `/settings/*`、`/user/*`、`/operation/*` |
完整 65 处见 `api.ts` 内 `【待确认】` 注释;精确清单应回到 `src/__tests__/backend-bridge-remaining.test.ts` 的 `FUNCS` 数组对照 OpenAPI 逐一校正。
---
## 四、整改建议(针对已转换接口)
1. **校正契约(P0)**:以《职来后端接口联调说明》`.docx`(§7 OpenAPI,`job.youthome.com.cn`)为唯一准绳,逐函数对照 65 个 `【待确认】` 路径,命中后删注释;**未对照前不宣布"已收口"**。
2. **让测试服务于真实契约(P0)**:把 `FUNCS` 数组路径从"占位"替换为经 OpenAPI 确认的路径;新增对拍用例(请求路径 + 响应字段 schema 校验),而非只断言前端猜的地址。
3. **统一已转换写接口 body 形态(P1-4)**:约定"整表替换类用 `{ items }`、单对象类用对象本体",`saveResumeExperience` 当前裸传 `items` 需包裹。
4. **修正 Token 有效期语义(P1-2)**:后端不返回 `expiresAt` 时不要用 `TOKEN_TTL_MS` 兜底成假 TTL;改为"不预判、靠 401 触发刷新 + 可选短轮询",或强制后端下发 `expiresAt`。
5. **补全 `/auth/me` 角色权威化(P1-3)**:微信登录 / 验证码登录 / 注册完成三个入口登录后统一调 `/auth/me` 并 `setRole`,与密码入口一致。
6. **清理 JSDoc(P2-1)**:批量清除 157 处 `@url /api` 旧前缀。
7. **明确双真相源切换策略(P2-3)**:在登录流程或"清除缓存"中,翻真实态前提示并清空本地覆盖层,避免数据幽灵。
8. **重写状态文档(P1-1)**:`后端联调前端实现.md` 按代码现状重标已转换接口,删除"未接后端"的误述。
---
## 五、验收口径(建议写入 AGENTS.md)
> **"接口已联调完成"的定义应为**:① 路径经 OpenAPI 校正并删除 `【待确认】`;② 至少一次真实联调(`apiUseMock=false`)返回符合类型定义的响应;③ 测试断言的是真实路径 + 响应字段。
> 仅凭"代码里写了 `request()`"或"测试命中占位路径"**不算完成**。

BIN
职来后端接口联调说明.docx

Binary file not shown.
Loading…
Cancel
Save