# AI-004 简历模块批量 AI 优化前端对接方案 日期:2026-10-29(Asia/Shanghai)。依据:用户已批准AI-004 v1.1,并明确三个总入口使用同一流程。状态:接口与调用契约已按当前源码及静态OpenAPI复核;前端队列尚未实施/联调,AI-003仍为未完成验收的候选实现。本文件不代表页面功能已上线。 ## 1. 三个入口与功能范围 “优化简历”“AI一键优化”“一键全部优化”共用同一批量启动处理函数、队列和运行状态,不分别创建请求流程。任一入口触发后,其他总入口显示同一进度并防止重复创建批次。原模块AI按钮继续提供单项优化,但与批量队列共用该页面的请求调度,避免同用户同时发起两个真实请求。 处理顺序:工作经历各条→实习经历各条→项目经历各条→自我评价。每次提交一条,每返回一条立即展示,不等待整个批次完成。用户确认建议与生成后续建议可交错进行。 只处理有原文且已具备AI接口的模块。空白、明确无事实的占位内容跳过并解释;不增加技能优化,不生成空经历或空自评,不解析附件,不关联评分。工作和实习均来自现有workExperiences,按experienceType及页面既有分类处理;同一条id只进入一次,不能因分别扫描两个列表重复优化。类型未区分时沿用原页面分类,不推断为实习或改写类型。 ## 2. 环境、鉴权与实际接口 将下列路径拼接到团队确认的后端origin,例如本机确实已启动服务时可使用 `http://127.0.0.1:8080`。本轮未启动服务或确认该地址在线;不要把示例当作当前可用联调环境。 全部请求使用 `Authorization: Bearer `;POST使用 `Content-Type: application/json`。限STUDENT本人,不提交userId。不把token、简历文本或模型响应写入普通日志/埋点。同步JSON,无分页、无SSE、无新增批量路由。 | 模块 | GET告知 | POST生成 | | --- | --- | --- | | 工作/实习 | `/api/v1/profile/me/work-experience-optimization/notice` | `/api/v1/profile/me/work-experience-optimization` | | 项目 | `/api/v1/profile/me/project-experience-optimization/notice` | `/api/v1/profile/me/project-experience-optimization` | | 自评 | `/api/v1/profile/me/self-evaluation-optimization/notice` | `/api/v1/profile/me/self-evaluation-optimization` | notice使用ApiResponse包装,data含 `version,title,provider,purpose,dataFields,message,mode,enabled,developmentOnly`。注意实际字段是 **version**,POST映射为 **consentNoticeVersion**;不存在新设计的retentionPolicyStatus或resume总场景notice。不能仅凭developmentOnly=false或enabled=true认定供应商正式政策、生产验收已完成。 当前源码版本:工作/实习 `work-experience-external-processing-v2`;项目 `project-experience-external-processing-v1`;自评 `self-evaluation-external-processing-v1`。客户端必须读取notice.data.version,不硬编码版本。 ## 3. 输入字段与映射 | 场景 | 业务字段及长度 | 从页面读取 | | --- | --- | --- | | 工作/实习 | position可选≤100;description必填非空≤3000;targetPosition可选≤100 | 当前条目position、description;当前求职意向targetPosition | | 项目 | projectName可选≤150;role可选≤120;description必填非空≤5000;targetPosition可选≤120 | 当前项目name映射projectName,role及description | | 自评 | description必填非空≤5000;targetPosition可选≤120 | selfEvaluation映射description | 各场景另有两个必填字段:externalProcessingConsent为原生JSON布尔true;consentNoticeVersion为该场景当前notice版本。字符串"true"、false、数字、null或缺失不合法。长度按Java字符串UTF-16长度;不自动截断。现有在线简历工作position/description上限大于工作AI上限,超出时标记待调整,不能截取后悄悄提交。可选目标岗位超限也不能自动截断,提示用户缩短或明确不提交该可选项。 仅发送上表及两个告知字段。条目id、revision、批次id、本地关联key、experienceType、公司、日期、姓名、联系方式、附件和完整简历不属于AI请求。条目映射保存在前端本次任务内存中,通过发起调用的任务对象关联响应,后端不会返回条目id。 工作/实习合成示例(代码中的noticeVersion变量来自GET告知): ```javascript const body = { position: entry.position, description: entry.description, targetPosition: targetPosition || null, externalProcessingConsent: true, // 仅在用户已明确同意该次请求后构造 consentNoticeVersion: noticeVersion }; ``` 项目合成JSON: ```json {"projectName":"课程商城","role":"参与开发","description":"使用Java实现订单查询接口,尚未上线。","targetPosition":"Java后端开发","externalProcessingConsent":true,"consentNoticeVersion":"project-experience-external-processing-v1"} ``` 自评合成JSON: ```json {"description":"学习Java和SQL,在课程项目中编写接口测试。","targetPosition":"Java后端开发","externalProcessingConsent":true,"consentNoticeVersion":"self-evaluation-external-processing-v1"} ``` ## 4. 告知与任务授权 当前正式代码告知写明“同意仅针对本次优化请求”,本次交付不改该约定。采用逐项明确同意:在每项派发前展示对应告知及处理条目,用户选择本次同意后调用;用户拒绝则跳过该项,继续下一项。可以用持续更新的单个确认面板避免重复弹窗,但不能自动勾选、把“点击总入口”当成外传同意或复用上次单项同意。 将“已读取该场景notice”与“用户已同意某条请求”分开保存。notice可在同批次同场景复用读取结果;若收到告知失效相关400,刷新notice、重新展示,让用户再次确认,不静默重试。现有400并无专门子码标明是否告知过期,不能把所有400都解释为版本过期,应先比较新notice版本及检查本地输入,仍无法判断则展示安全错误和requestId。 “一个界面勾选全部条目一次授权自动派发”的体验没有在本次交付中认定为满足既有每次请求告知;若要采用,须先明确其条目范围及正式告知规则再更新对接约定。用户逐一确认优化结果与用户同意向第三方处理是两个不同动作。 ## 5. 队列、调用节奏与结果 进入批次时固定清单,每项保留本地taskKey、场景、条目id或本地稳定key、原文、请求字段快照及generation。这些字段不发给AI。批次进行中新增的经历不自动加入已获同意的清单,另起处理。 全页面同一时刻最多一条AI请求。真实模式默认限额为每用户3次/分钟、20次/天、全局200次/天、全局并发4,均是现有配置默认值,部署可能覆盖。计数按Redis时间固定窗口、日窗口为UTC;不要展示北京时间零点必定恢复。notice不返回额度余额,页面不能显示虚构的“剩余次数”。 若联调确认为默认3次/分钟,可将真实请求开始间隔至少21秒,模型调用耗时和等待用户确认均计入间隔;部署限额不同则由前端按联调配置调整。此为减少429的调度建议,不能消除其他页面、其他入口、全局或日限额竞争,仍必须处理429。stub模式无需人为等待21秒。等待以可取消的异步计时器实现,不阻塞页面,不同时派发多条。 所有生成响应沿用以下结构: ```json {"code":200,"message":"ok","data":{"status":"OPTIMIZED","optimizedDescription":"参与订单查询接口开发,并补充接口测试。","suggestions":[],"followUpQuestions":[],"promptVersion":"work-experience-deepseek-v2","simulated":false},"requestId":"example","timestamp":"2026-10-29T02:00:00Z"} ``` | 返回内容 | 界面处理 | | --- | --- | | OPTIMIZED且有正文 | 显示原文和建议,进入待确认 | | NEED_MORE_INFO | 显示问题;optimizedDescription可能省略或null,禁止清空原字段 | | simulated=true | 显示模拟标识;可能仍为OPTIMIZED并原样返回原文,不宣称润色成功 | | simulated=false | 仅说明当前模式;本地规则可能直接返回,不证明本次实际外呼 | | 未知status或结构不完整 | 视为本项异常,不回填、不保存,保留原文 | 现有接口没有UNCHANGED或批量status,不创建假后端状态。前端自身可使用待处理、等待同意、等待额度、处理中、待确认、需补充、失败、跳过、取消;采用和保存另记状态。进度分别显示“已处理/总项”“生成建议数”“待确认数”“已保存数”,不能把生成成功展示为保存成功。 用户取消时停止尚未派发的调用;给正在执行的task标记失效,晚到响应不覆盖新批次。AbortController可停止等待,但不保证供应商停止计算或退费。不自动持久化正文到localStorage/IndexedDB;页面离开、账号退出清理内存建议,不承诺离开后继续运行。 ## 6. 逐项确认、编辑与原保存 每项结果有查看、修改建议、采用、取消。修改后的建议仍受原模块字段长度限制。采用前对比稳定条目身份和目标原文;描述已编辑、条目删除或用户切换账号时标记过期,允许查看/复制但不自动覆盖。不能按数组下标定位条目,也不能用其他条目的建议替换它。 工作/实习/项目仅回填description,自评仅回填selfEvaluation。不要求页面进入整份简历编辑。用户采用后可以继续编辑;保存走原模块工具。若该工具为“确认即保存”,按钮需明确含保存动作,由其原有行为执行,不新增AI自动保存请求。 已核查的后端保存契约: | 方法/路径 | 用途与注意 | | --- | --- | | GET `/api/v1/profile/me/online-resume` | 读取content与全局revision | | PUT `/api/v1/profile/me/online-resume/work-experiences/{id}` | 工作/实习条目完整替换,请求为revision、entry | | PUT `/api/v1/profile/me/online-resume/project-experiences/{id}` | 项目条目完整替换,请求为revision、entry | | PUT `/api/v1/profile/me/online-resume` | 现有完整保存;自评没有独立section写接口,原工具若使用此接口必须保留全部content | 条目保存合成示例: ```json {"revision":3,"entry":{"id":"11111111-1111-1111-1111-111111111111","company":"示例公司","position":"实习开发","startDate":"2026-01-01","endDate":null,"ongoing":true,"experienceType":"INTERNSHIP","description":"用户确认并编辑后的描述"}} ``` 这是示例字段值,不可用示例id调用真实保存。实际应完整复制原条目所有业务字段,只替换目标描述。新条目没有服务器id时沿用原新增工具,不伪造id。 保存响应data是更新后的完整OnlineResumeView(revision、content、attachment、updatedAt);下一项采用保存以新revision为准,同时保留其他尚未保存的建议/编辑状态,不能刷新视图时丢掉它们。所有页面保存共用串行写入管理,不能让两个保存请求同时使用旧revision。HTTP409/code6002需重新读取并人工合并,HTTP404/code6003表示条目不存在,禁止改为创建或强行覆盖。 自评完整保存只提交 `{revision,content}`,content为原工具维护的完整最新内容,不能只构造selfEvaluation一个字段。其他模块在生成期间已被保存的变动也要保留。前端实际使用哪个原工具及其返回处理仍需负责人用调用片段联调确认,不因后端提供整份PUT就改变页面编辑方式。 ## 7. 错误、超时、重试 按HTTP状态和现有业务码共同处理,不能只判断code是否等于HTTP状态。错误data可能因NON_NULL省略。 | HTTP | 行为 | | --- | --- | | 400(可能code400/1001) | 本项失败;保留原文,检查长度/敏感输入/同意/版本;继续其他合法项,不自动重试 | | 401 | 停止队列,走原会话流程;新账号不得继承旧队列 | | 403(角色可能code2002)/404用户不存在 | 停止队列,提示权限或账号不可用 | | 429 | 暂停派发,保留所有结果;当前返回Retry-After:60,倒计时后允许手动继续,不保证日额度已恢复 | | 502/504或网络超时 | 当前项失败,保留其他结果;允许单项手动重试,重新明确同意,不后台补发 | | 503 | 暂停队列并提示模块关闭/配置/Redis/上游问题,不循环重试;可由用户跳过不可用场景 | | 500 | 保留当前结果和原文,暂停并展示requestId,供联调定位 | 模型默认超时20秒,可配置1–60秒;前端请求超时需高于实际后端超时并留网络余量,不把请求超时设为整个批次超时。多条队列总时长可能更长,持续显示进度及取消入口。计费是否发生不能仅凭超时或simulated=false判断。 ## 8. 联调验收清单与状态 已完成:按源码复核六条AI路由、告知字段/版本、请求上限、响应、角色和错误;现有OpenAPI脚本2026-10-29运行通过(217 paths/265 operations)。这属于静态契约验证,不代表服务已部署。 待前端负责人联调:三个总入口同队列;工作/实习去重;逐条返回与逐项授权;空模块/不可用场景;超长输入不截断;429暂停/继续;取消和晚到结果;编辑后过期提示;确认后继续改写;保存串行revision;409冲突;保存后重开回读;评分、技能、附件及原单项按钮不被改变。 当前无已确认的在线联调URL;AI-003有未完成验收事项,真实模型质量、供应商正式告知、Redis运行验证和页面验收本轮未执行。先在团队可用stub环境验证契约和交互,模拟结果必须标注;真实模式开放由负责人在既有验收完成后决定。