# 职来(有职)前端 · 已转换接口(已"调过")存在的问题 > 生成日期: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()`"或"测试命中占位路径"**不算完成**。