30 KiB
后端 API 对接指南
前端四条演示流和演示预检已经稳定。后端 API 按页面逐刀接入,避免一次性铺满四个页面。
第一阶段范围
| 页面 | 后端接口 | 处理 |
|---|---|---|
AI面试 /recruit/interview |
POST /api/recruit/interview/start、/answer、/finish、GET /records、POST /records/{sessionId}/review |
已接入真实模型优先链路:配置 chat 模型后 /start 动态生成面试题,/finish 按前端提交的真实回答做结构化评分;未配置模型时使用本地 Rubric 估分,不返回固定候选人分数。AI 分数只作辅助参考,HR/管理员可提交 reviewedScore/reviewNote 完成人工复核;记录同时保留 AI 分、人工复核分、最终采用分和复核状态 |
候选人入职主体关联 /recruit/interview |
GET/POST /api/recruit/interview/candidate-links |
HR/管理员在当前租户范围内把本地候选人 ID 关联到已同步的在职 ext_party_id;只保存外部主体 ID,不复制姓名、部门等组织字段,重复关联同一主体幂等,候选人更换主体或同一主体已关联其他候选人会拒绝 |
三角色对练 /train/practice |
POST /api/train/practice/start、/turn、/finish |
已接入编排 API;数据库启用 chat 模型后,/turn 客户回复按人设走真 LLM 生成(seed 剧本作剧情锚点),/finish 走单次 temperature=0 结构化评分(4 维分+导师改写+点评);移动端 turn/finish 校验当前手机号与启动会话归属,未知或他人会话拒绝;模型未配置或调用失败自动回退 seed,契约不变 |
| 正式试点数据导出 | GET /api/train/practice/export?startDate=YYYY-MM-DD&endDate=YYYY-MM-DD |
起止日期必填且包含结束日;只统计窗口内能通过唯一手机号或外部 ID 映射到在职组织快照的正式会话,排除重复手机号和身份碰撞。完训定义为每人至少 10 次,校准必须关联同一窗口内正式会话;CSV 同时给出校准命中数、SOP 可用数、满意度响应数/平均分,以及明细级 AI 分、人工校准分、校准人、校准时间、最终采用分、满意度分和意见,避免用四舍五入后的比率反推门禁状态;汇总和明细均携带正式人员及项目口径,不混入历史 seed/开发身份 |
| 对练语音 | POST /api/ai/asr(multipart 字段 file,≤5MB)、POST /api/ai/tts(JSON {text≤300字, voice},成功返回 ossId,客户端播放地址为受控的内联 data:audio/*,不返回原始 OSS URL)、GET /api/aihr/mobile/oss/{ossId} |
走 OpenAI-compatible audio 接口(如硅基流动 SenseVoice/CosyVoice2);模型管理需启用 category=asr/tts 配置;移动端优先用浏览器录音,getUserMedia/MediaRecorder 不可用或麦克风权限失败时,用 audio/* file input 选择/录制音频后继续调同一 ASR 接口;ASR/TTS 未配置或失败返回 fail,前端降级文本;训练/每日题录音只通过 audioOssId 走受保护下载,历史客户端传入的 HTTP audioUrl 不再回显;TTS 成功音频仍写入 sys_oss 留痕,同时用内联 data URL 保持旧客户端可播放;音频下载按员工本人或主管项目范围授权,系统管理端保持后台访问 |
案例沉淀 /knowledge/cases |
GET /api/knowledge/case/capabilities、POST /api/knowledge/case/upload、/organize、/curate、GET /records、GET /records/{caseId}、POST /records/{caseId}/review、GET /records/{caseId}/media |
/capabilities 返回服务端判定的案例提交/查看能力,移动端不再向普通员工展示无权提交的素材表单;/upload 改为 multipart 真实语音上传并走 ASR,服务端只接受 MP3/WAV/M4A/WebM/OGG/AAC/FLAC,成功后原始音频写入 sys_oss,案例记录只保存 mediaOssId 供受保护媒体接口读取,不向客户端回传原始 mediaUrl;/organize 用真实转写调 chat 模型整理案例,未配置模型时按真实 transcript 本地结构化,并从背景外的真实摘要项提取学习点;APP 用户的项目范围从 aihr_org_snapshot 登录身份解析,上传、整理、入库、列表和详情均按项目范围校验,未完成正式组织映射时安全拒绝,不接受前端伪造项目范围;员工列表/详情只返回 已入库 案例,管理端系统用户保留全局运营视图;移动端和管理端案例详情通过受保护媒体接口回放原始音频,主管/项目负责人可提交脱敏点评;预渲染视频样片仍待正式媒体资产接入 |
| 案例媒体安全 | GET /api/knowledge/case/records/{caseId}/media |
案例详情只返回 mediaOssId,不返回原始 sys_oss.url;媒体下载会重复执行登录、后台角色或 APP 项目范围校验,再由服务端流式读取 OSS。管理端与 mobile-uni 通过鉴权 blob/temp 文件播放,关闭详情页时释放本地对象 URL |
SOP知识库 /knowledge/sop |
POST /api/knowledge/search、POST /api/knowledge/answer-feedback、GET /api/knowledge/position-sop、GET /api/aihr/mobile/onboard/tasks、POST /api/aihr/mobile/onboard/tasks/{id}/complete、GET /api/aihr/mobile/qualification、POST /api/knowledge/doc/upload |
已接入 MySQL Fulltext + Qdrant 混合召回、岗位学习适配摘要、OSS-first 文档上传、txt/md/PDF/Word/Excel/PPT 解析和 embedding 写入,失败回退 seed;搜索返回 reviewId 与 promptVersion,员工反馈回传并保存该评审批次,SOP 人工评审记录同时保留答案生成提示词版本,管理端可继续复核;员工学习页按当前 APP 身份读取正式岗前/入职任务,员工只能将本人处于“待完成/进行中”的任务确认完成,服务端按组织快照/手机号归属更新 status/completed_time,不接受前端身份参数;资格证据无正式数据时明确返回 NOT_CONFIGURED,不以 AI 分数代替上岗资格;position-sop 仍保留一期生活顾问学习导航语义 |
资料处理 /knowledge/processing |
GET /api/knowledge/processing/overview、POST /api/knowledge/doc/upload-async、GET /api/knowledge/doc/upload-items、POST /api/knowledge/doc/upload-items/{id}/retry、POST /api/knowledge/doc/import-local-task、GET /api/knowledge/doc/import-tasks、POST /api/knowledge/doc/import-tasks/{id}/cancel |
已接入解析任务状态聚合;批量上传走异步队列:接口只暂存+入队即秒回,后台 worker(并发 2)逐条解析/归类/向量化;ZIP 在 worker 内安全解压后把支持的子文件继续入同一批次队列,页面按批次轮询进度、失败可单文件重试;服务端目录导入、进度轮询和任务取消保留,失败回退 seed |
| 组织人员同步 | POST /api/aihr/org/sync |
从开放组织同步系统的 /api/open/v1/sync/snapshot 拉取 company/department/employee 快照,分页参数使用 limit;员工手机号只落 person_phone 用于移动端身份映射,不在组织列表响应暴露;岗位识别 position/job_title/post/job_name/role/title 等字段。dryRun 必须显式传入 true(预检)或 false(写入),省略或传 null 直接拒绝,避免空请求意外写库;默认 replaceExisting=true,写入前必须先用 {"dryRun":true};dry-run 不访问本地快照表、不执行 DDL/写库,返回 phoneLinked/maskedPhone/suspectText/warnings 且 syncedCount=0。非 dry-run 覆盖写入遇到员工被跳过、手机号不完整、脱敏手机号或疑似乱码时默认拒绝,只有确认 dry-run 结果后显式传 allowPartialReplace=true 才允许覆盖;重复 ext_party_id 始终拒绝写入,因为数据库唯一键会折叠重复身份;replaceExisting=false 不触发不完整快照覆盖闸门,但仍拒绝重复身份。2026-07-10 源接口实测 3474 人仅 1 个可用手机号、3473 个脱敏手机号、8 条疑似乱码,因此未执行覆盖同步,正式试点需上游先开放至少 20 名试点人员手机号 |
| 移动端手机号登录 | GET /resource/sms/code、POST /auth/mobile/sms-login |
已复用 sms4j 阿里云配置 config1 和 RuoYi sms 授权策略;短信发送成功后才写 Redis 验证码;手机号不存在时自动注册 app_user;aihr.sms.dev-fixed-code 非空时不真发短信、验证码固定(dev 默认 123456,prod profile 代码级强制失效) |
用户侧三端首页 mobile-uni hash 路由;旧 /h5/user、/h5/candidate、/h5/supervisor 兼容重定向 |
GET /api/aihr/mobile/home/{role} |
未登录请求只返回不读取租户业务统计的公开首屏 seed;已登录移动端请求自动携带 Authorization/clientid,才返回员工/主管真实统计;移动端本地 fallback 保演示 |
| 移动端登录后角色识别 | GET /api/aihr/mobile/me |
认证后按手机号匹配组织快照;position_level 为“主管/项目经理”时进入主管端,否则进入员工端;接口失败回退员工端 |
| 移动端员工训练与主管复盘闭环 | 员工复用 POST /api/train/practice/start、/turn、/finish,查询 GET /api/aihr/mobile/practice/history、/practice/mistakes、/profile;训练完成后提交 POST /api/aihr/mobile/practice/satisfaction;主管查询 GET /api/aihr/mobile/practice/team、/practice/alerts、/practice/reviews、/practice/reviews/{id},标记 POST /api/aihr/mobile/practice/reviews/{id}/reviewed,指派 POST /api/aihr/mobile/practice/assignments |
员工端登录后带 Authorization 与 clientid 调用;mode=mobile 完成后写入 aihr_practice_session。满意度接口只接受本人已完成训练的 1-5 分,意见脱敏后落库,未填写不补默认值。错题本按员工本人聚合低分/红线回合,并关联已有 retry assignment,不伪造错题结论。主管 /practice/team 在同一项目权限范围内额外返回 mistakes 聚合,按场景/归因统计次数、影响人数、平均分和最近发生时间;普通员工返回“无主管权限”。主管接口以后端当前登录手机号映射在职组织快照,仅允许岗位为“主管/项目经理”的账号,并按租户和项目范围返回真实成员、全状态训练记录及非 daily 专项。复盘标记只允许首次 待复盘 -> 已复盘 创建后续专项,并发重复提交幂等;可带 incentivePoint 写入贡献度。每日三题正式只对 hire_date 在当前日期前三个月内的在职员工派发;没有入职日期时不使用训练次数推断,开发 Demo 的旧回退只有在 dev/local profile 且由 aihr.practice.allow-legacy-daily-drill-fallback 显式开启时生效,生产 profile 强制关闭。 |
| 移动端候选人闭环 | 页面拆为 /pages/candidate/index/index、/interview/index、/materials/index、/progress/index、/study/index;面试复用 POST /api/recruit/interview/start、/answer、/finish 和 GET /records;资料 POST/GET /api/aihr/mobile/candidate/materials;预习 POST /api/knowledge/search;HR 审核 GET /api/aihr/hr/candidate/materials、POST /api/aihr/hr/candidate/materials/{id}/review |
候选人端登录后带 Authorization 与 clientid 调用;首页只按当前手机号对应的真实面试记录和最新资料状态分流,不读取公开 home seed。APP 候选人身份以后端登录手机号为准,前端 candidateId/candidateName 只作非 APP 场景兼容参数;面试支持文字作答和复用 /api/ai/asr 的录音转文字/选音频,/answer 可带可选 answerAudioOssId,服务端只接受当前候选人名下处于 staged/bound 状态的音频并将 ossId 写入问题快照,不向客户端暴露原始 OSS URL;/answer 与 /finish 还会校验当前 APP 手机号与启动会话的候选人 ID 一致,未知或他人会话直接拒绝;面试拉题/评分走真实模型优先;资料写 sys_oss/MinIO 和 aihr_candidate_material,HR 审核后进度页同步三态;岗前预习查询正式 SOP,不兜前端示例答案 |
后端落点
- 业务模块:
backend/ruoyi-modules/ruoyi-aihr - 注册模块:
backend/ruoyi-modules/pom.xml - 接入启动包:
backend/ruoyi-admin/pom.xml - 包名建议:
org.dromara.aihr - Controller 返回统一用
org.dromara.common.core.domain.R
当前管理端 AI 面试和案例沉淀已改为真实模型/ASR 优先;移动端首页和部分演示态数据仍保留 fallback。知识库、模型能力、文档解析、RAG、chat 按 ruoyi-ai 能力分片迁移计划 逐片引入;知识库 DDL 与住宅类 SOP seed 在 backend/script/sql/aihr_knowledge_mysql8.sql,模型 DDL 在 backend/script/sql/aihr_model_mysql8.sql,训练记录 DDL 在 backend/script/sql/aihr_practice_mysql8.sql,AI 面试结果 DDL 在 backend/script/sql/aihr_interview_result_mysql8.sql,候选人资料 DDL 在 backend/script/sql/aihr_candidate_material_mysql8.sql,组织人员快照表在 backend/script/sql/aihr_org_snapshot_mysql8.sql,本地 reset 带 2 个住宅项目 22 人 seed;配置开放组织同步系统后用 POST /api/aihr/org/sync 覆盖为外部快照。
直接打后端 /api/** 通常需要登录后的 Authorization: Bearer <access_token>;浏览器内通过已登录前端和 /dev-api 代理访问。移动端登录接口为 POST /auth/mobile/sms-login,请求 { phonenumber, smsCode, tenantId },内部固定使用 app 客户端 428a8310cd442757ae699df5d894f051 和 sms grant;验证码通过后若手机号不存在,会创建 app_user,用户名为手机号,备注为“移动端短信自动注册”。移动端首页接口 GET /api/aihr/mobile/home/{role} 仍保留 @SaIgnore 以保证未登录首屏可用,但匿名分支只返回不读取业务统计的公开 seed;登录后的 mobile-uni 会自动携带移动端 token,服务端才返回真实员工/主管统计。
阿里云短信复用 RuoYi 的 sms.blends.config1。本地开发把真实短信参数放根目录 .env.local 或外部环境变量,scripts/dev-backend.sh 会自动加载;application-dev.yml / application-prod.yml 只保留占位,不写真实密钥。
AIHR_SMS_LOGIN_TEMPLATE_ID=SMS_xxxxxx
ALIYUN_SMS_ACCESS_KEY_ID=xxx
ALIYUN_SMS_ACCESS_KEY_SECRET=xxx
ALIYUN_SMS_SIGN_NAME=物业AI助手
候选人资料上传最小后端边界:
| 能力 | 后端接口 | 处理 |
|---|---|---|
| 候选资料上传 | POST /api/aihr/mobile/candidate/materials |
multipart/form-data 字段 file,参数 candidateId/candidateName/materialType;需移动端登录返回的 Authorization 与 clientid;APP 用户场景后端强制使用登录手机号和派生候选人名,不信任前端传入身份;服务端与移动端共同限制 PDF/Word/JPG/PNG/WebP,文件名会去掉路径和控制字符;文件用 ISysOssService 写 sys_oss/MinIO,关系写 aihr_candidate_material,状态默认 待审核,单文件 20MB |
| 候选资料列表 | GET /api/aihr/mobile/candidate/materials?candidateId= |
返回前 20 条 {id, ossId, fileName, materialType, fileSize, status, time},供 /h5/candidate 的“已提交资料”展示;APP 用户场景忽略传入 candidateId,只返回登录手机号对应资料 |
| HR 资料审核 | GET /api/aihr/hr/candidate/materials?status=、POST /api/aihr/hr/candidate/materials/{id}/review |
管理端 /recruit/interview 展示前 50 条,可按状态筛选;审核请求体 {status},只接受 待审核/已通过/已驳回;接口只允许管理端超级管理员或 hr_operator 角色访问 |
SOP 文档上传第三片已经落最小后端边界:
| 能力 | 后端接口 | 处理 |
|---|---|---|
| 文档上传解析 | POST /api/knowledge/doc/upload |
multipart/form-data,字段 file 和 category;支持 .txt/.md/.markdown/.pdf/.doc/.docx/.xls/.xlsx/.ppt/.pptx 及图片 .jpg/.jpeg/.png/.gif/.webp/.bmp、100MB 内;先写 sys_oss,再绑定 aihr_knowledge_attach.oss_id 并切分写入 aihr_knowledge_fragment;管理端该接口 timeout 为 180s,避免 PDF 同步解析/归类/向量化接近默认 50s 时被客户端断开 |
| 图片视觉 OCR | 同一上传/导入链路 | 上传图片时,若启用了 aihr_model_config.category='vision'(无则回退 category='chat')的模型,会把图片编码为 base64 data URL 调用该供应商 OpenAI-compatible /chat/completions 提取文字,识别结果按普通正文切分写入 fragment;无可用视觉模型或 OCR 无结果时按「待处理」落库(attach status=0、0 片段),不算失败,启用视觉模型后重新上传同名文件即可解析。不依赖 Tesseract,识别质量由所配置视觉模型决定 |
| 智能归类与标签 | 同一上传/导入链路 | category=__auto__ 时,解析正文后优先调用已启用的 aihr_model_config.category='chat' 模型生成分类、摘要、标签和归类理由,温度固定为 0;无模型或调用失败时按文件名/正文关键词兜底。最终分类写入 aihr_knowledge_info/attach,摘要和标签写入 sys_oss.ext1 |
| 重复资料处理 | 同一上传/导入链路 | 上传时计算原始文件 aihrFileSha256、解析文本 aihrTextSha256 和 md5 写入 sys_oss.ext1;重复判断优先按文件 SHA-256,其次按文本 SHA-256,最后用同名同大小兼容旧数据。命中重复时复用原附件并迁移到最新分类,删除其他重复附件和旧 fragment |
| 归类稳定性 | 同一上传/导入链路 | 命中重复资料时优先复用已有 sys_oss.ext1 里的分类、摘要和标签;只有旧资料没有存过模型结果时才重新分析,避免同文件因重复上传或更换模型导致标签漂移 |
| 文档替换 | 同一 category + fileName 再上传 |
复用原 doc_id,删除旧 fragment 后重写新 fragment,避免重复文档堆积 |
| 片段向量化 | 同一上传接口内机会性执行 | 若 aihr_model_config.category='vector' 且启用,会优先调用配置供应商的 OpenAI-compatible /embeddings,把返回向量写入 aihr_knowledge_fragment.embedding_json;配置缺失或外部接口失败时使用本地确定性 local-hash-v1 兜底,保证 MVP 链路仍有真实向量数据 |
| 缺失向量补跑 | POST /api/knowledge/doc/vectorize-missing |
扫描缺少 embedding_json 的片段,复用同一向量化与 Qdrant 入库链路,适合模型配置变更后或历史资料补齐向量 |
| 向量库状态与重建 | GET /api/knowledge/doc/vector-index-status、POST /api/knowledge/doc/rebuild-vector-index |
模型配置页展示当前 vector 模型维度、Qdrant collection 维度、点数和片段向量数;维度不一致时可一键清空旧 embedding、删除 collection 并按当前模型重建 |
| Qdrant 向量索引 | 同一上传接口内机会性执行 | embedding 写入 MySQL 后尽力 upsert 到 Qdrant;同名文档替换会尽力删除旧 points;Qdrant 不可用不影响上传和 MySQL 检索;外部 embedding 成功但 collection 维度不一致时不静默降级为 local-hash-v1,通过状态接口和重建入口处理 |
| 混合检索 | POST /api/knowledge/search |
先跑中文关键词 LIKE 打分和 MySQL Fulltext,再生成 query embedding 走 Qdrant,RRF 融合后交给 category='rerank' 模型(如硅基流动 bge-reranker-v2-m3)按语义相关性重排;rerank 未配置或失败保持 RRF 顺序,Qdrant 或外部向量接口不可用时保留关键词/全文检索。命中后若 chat 模型可用,自动生成结构化轻概要写入响应 answer/keyPoints/cautions(≤60字直答+3-6要点+0-3注意;temperature=0,15s 超时,硬约束不得编造、答不了明示无依据);概要失败回退片段原文拼接,检索不报错 |
| 检索总结卡 | POST /api/knowledge/summary-card(JSON {queryText, category}) |
按需生成信息图式总结卡 {title, steps[], objections[], scripts[], reminders[]}:复用检索命中片段(最多5条)调 chat 模型,temperature=0、30s 超时;无命中/无 chat 模型/生成失败均抛明确错误供前端重试,不兜假数据。移动端查SOP结果页「生成总结卡」按钮触发,底部弹层展示并可 TTS 朗读 |
| 解析状态聚合 | GET /api/knowledge/processing/overview |
聚合 aihr_knowledge_attach.status、fragment 数、embedding 数、sys_oss.ext1.fileSize,生成资料处理页指标、分类、任务、链路和事件列表 |
| 服务端目录导入 | POST /api/knowledge/doc/import-local |
JSON { directory, category, limit };directory 只能是 AIHR_IMPORT_ROOT / aihr.import.root 下的相对目录,默认根目录为 ./.data/import;逐文件复用上传解析链路,同步执行,保留给小批量/调试 |
| 服务端导入任务 | POST /api/knowledge/doc/import-local-task、GET /api/knowledge/doc/import-tasks、POST /api/knowledge/doc/import-tasks/{id}/cancel |
启动后台目录导入并返回任务;任务写入 aihr_knowledge_import_task,页面轮询查看总数、成功数、失败数、当前文件和进度;运行中任务可取消;重试当前按同目录重新启动一轮 |
| 批量异步上传 | POST /api/knowledge/doc/upload-async(multipart file+category+batchId)、GET /api/knowledge/doc/upload-items?batchId=、POST /api/knowledge/doc/upload-items/{id}/retry |
上传只做暂存(aihr.upload.staging,默认 ./.data/staging)+ 写入 aihr_knowledge_upload_item(0待处理/1处理中/2完成/3失败)即返回;支持 ZIP ≤500MB,worker 限制最多 1000 个子文件、解压总量 ≤2GB,拒绝嵌套 ZIP/不安全路径并忽略未知格式;支持的子文件写回同一 batch 继续复用解析链路;完成/失败状态 CAS 写入,卡住 30 分钟(视频 120 分钟)由清扫重置,失败暂存文件保留 72h 供重试;同步接口 POST /api/knowledge/doc/upload 不支持 ZIP,保留给 SOP 页单文件即时预览 |
| 视频解析 | 走批量异步上传,支持 .mp4/.mov/.avi/.mkv/.webm/.m4v,单文件 ≤500MB、时长 ≤60 分钟 |
依赖服务器 ffmpeg/ffprobe;抽音轨按 5 分钟分段调 asr 模型转写([mm:ss] 时间戳),按 30s 间隔(≤40 帧)抽关键帧调 vision 模型提取画面文字(相邻重复画面去重);两类文本合并后走归类/切片/向量化;无 asr 且无 vision 结果时按「待处理」落库不报错;视频同时只加工 1 个 |
模型能力第二片已经落最小后端边界:
| 能力 | 后端接口 | 处理 |
|---|---|---|
| 模型供应商 | GET /api/aihr/model/providers、POST /api/aihr/model/providers、PUT /api/aihr/model/providers/{providerCode}、PATCH /api/aihr/model/providers/{providerCode}/status |
优先返回 aihr_model_provider,支持新增、编辑、启停;缺表或空表时返回 seed 清单 |
| 模型配置 | GET /api/aihr/model/configs、POST /api/aihr/model/configs、PUT /api/aihr/model/configs/{id}、PATCH /api/aihr/model/configs/{id}/enabled |
优先返回 aihr_model_config,支持新增、编辑、启停,并计算是否已具备 URL/Key;category 支持 chat/vector/rerank/asr/tts/vision |
| 模型探针 | POST /api/aihr/model/chat |
数据库配置后走 OpenAI-compatible /chat/completions,否则 seed fallback;请求携带的模型名在库中不存在时(如前端 seed 占位行 gpt-4o-mini),自动回退到默认已启用的 chat 配置 |
本阶段不修改 .env,也不自动执行模型 SQL。API Key 通过模型配置页面写入数据库:api_key 可放在 aihr_model_provider 作为供应商默认值,也可放在 aihr_model_config 覆盖单个模型;接口响应只返回 configured/apiKeyConfigured,不返回密钥明文。
Qdrant 本地默认值可不配;需要覆盖时用 JVM property 或环境变量:
| 配置 | 默认值 | 用途 |
|---|---|---|
AIHR_QDRANT_URL / -Daihr.qdrant.url |
http://127.0.0.1:6333 |
Qdrant REST 地址 |
AIHR_QDRANT_COLLECTION / -Daihr.qdrant.collection |
aihr_knowledge |
知识库向量 collection |
AIHR_QDRANT_API_KEY / -Daihr.qdrant.apiKey |
空 | 远端 Qdrant API Key,本地不用 |
AIHR_IMPORT_ROOT / -Daihr.import.root |
./.data/import |
服务端资料目录导入根目录 |
组织人员同步配置:
| 配置 | 默认值 | 用途 |
|---|---|---|
AIHR_ORG_SYNC_BASE_URL / -Daihr.org-sync.base-url |
空 | 外部开放平台 /api/open/v1 前缀,例如 https://wuye.meihe.cc/api/open/v1 |
AIHR_ORG_SYNC_ACCESS_TOKEN / -Daihr.org-sync.access-token |
空 | 已有 Bearer token;为空时尝试用 client credentials 换 token |
AIHR_ORG_SYNC_CLIENT_ID / -Daihr.org-sync.client-id |
空 | 开放平台应用 client_id,也用于签名头 X-Client-Id |
AIHR_ORG_SYNC_CLIENT_SECRET / -Daihr.org-sync.client-secret |
空 | POST /auth/token 换取访问令牌 |
AIHR_ORG_SYNC_SIGNING_SECRET / -Daihr.org-sync.signing-secret |
空 | 可选 HMAC-SHA256 签名密钥;为空时使用 AIHR_ORG_SYNC_CLIENT_SECRET,业务请求带 X-Client-Secret/X-Timestamp/X-Nonce/X-Signature,签名 path 必须包含 /api/open/v1 |
本地启动脚本会先加载根目录 .env.local,再加载 backend/.env。如果 backend/.env 沿用开放平台字段名 client_id / client_secret,脚本会映射为 AIHR_ORG_SYNC_CLIENT_ID / AIHR_ORG_SYNC_CLIENT_SECRET。
TOKEN=<登录后 access_token>
API_BASE=${API_BASE:-https://wygj-api.localhost}
curl -fsS "$API_BASE/api/aihr/org/sync" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"dryRun":true}'
curl -fsS "$API_BASE/api/aihr/org/sync" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"dryRun":false,"replaceExisting":true,"allowPartialReplace":false}'
# 仅在 dry-run 已人工确认允许不完整快照覆盖时使用
curl -fsS "$API_BASE/api/aihr/org/sync" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"dryRun":false,"replaceExisting":true,"allowPartialReplace":true}'
前端落点
- 管理端前端:
frontend/,只承载后台管理、配置、审核、查看结果等页面。 - AI 面试 API 文件:
frontend/src/api/aihr/interview.ts - AI 面试页面:
frontend/src/views/recruit/interview.vue - 三角色对练 API 文件:
frontend/src/api/aihr/practice.ts - 三角色对练页面:
frontend/src/views/train/practice.vue - 案例沉淀 API 文件:
frontend/src/api/aihr/case.ts - 案例沉淀页面:
frontend/src/views/knowledge/cases.vue - SOP 知识库 API 文件:
frontend/src/api/aihr/sop.ts - SOP 知识库页面:
frontend/src/views/knowledge/sop.vue - 资料处理 API 文件:
frontend/src/api/aihr/processing.ts - 资料处理页面:
frontend/src/views/knowledge/processing.vue - 模型配置 API 文件:
frontend/src/api/aihr/model.ts - 模型配置页面:
frontend/src/views/system/model/index.vue - 用户侧工程:
mobile-uni/,路由为/h5/#/pages/user/today/index、/h5/#/pages/user/practice/index、/h5/#/pages/user/sop/index、/h5/#/pages/user/profile/index、/h5/#/pages/candidate/index/index、/h5/#/pages/supervisor/index/index。未登录先走手机号短信登录,登录后 API 优先请求真实业务接口,不复用后台页面路由。语音输入不要新增移动端专用接口,浏览器录音和文件选择兜底都复用/api/ai/asr。 - 员工端训练:底部“练”进入
/h5/#/pages/user/practice/index,展示今日任务、每日三题、专项训练、训练前预习卡和训练对话;每日三题支持文字或录音转写,作答接口/api/aihr/mobile/practice/assignments/{id}/answer可携带answer/audioUrl/audioOssId,服务端只持久化可安全回放的内联 data URL,OSS 音频通过audioOssId受保护下载;完成后记录写入aihr_practice_session,员工端可提交 1-5 分训练体验和可选意见,员工端展示训练历史和能力画像,主管端展示待复盘列表,点进单条可看评分、话术、导师改写,并可标记“已复盘”。能力画像按 BRD 五维返回任务完成度、话术规范性、情绪管理能力、响应时效、增值转化潜力;暂无工单/时效数据的维度返回null,前端显示“待采集”,不把训练次数当正式绩效指标。 - 候选人端:
/h5/#/pages/candidate/index/index的“开始面试/面试练习”复用 AI 面试 API;“补充资料”走候选资料上传接口,成功后展示资料类型和审核状态。管理端/recruit/interview底部展示“候选资料审核”,支持通过/驳回。 - 演示 fallback 只作为未配置模型或外部接口异常时的降级,不作为真实测试通过证据。
验收
./scripts/demo-check.sh
npm --prefix mobile-uni run build:h5
API_BASE=${API_BASE:-https://wygj-api.localhost}
curl -fsS "$API_BASE/api/aihr/mobile/home/user"
npm --prefix frontend run lint:eslint -- src/api/aihr/interview.ts src/views/recruit/interview.vue src/api/aihr/practice.ts src/views/train/practice.vue src/api/aihr/case.ts src/views/knowledge/cases.vue src/api/aihr/sop.ts src/views/knowledge/sop.vue
mvn -f backend/pom.xml -pl ruoyi-admin -am -DskipTests package
模型能力可单独 smoke:
TOKEN=<登录后 access_token>
API_BASE=${API_BASE:-https://wygj-api.localhost}
curl -fsS "$API_BASE/api/aihr/model/providers" -H "Authorization: Bearer $TOKEN"
curl -fsS "$API_BASE/api/aihr/model/configs" -H "Authorization: Bearer $TOKEN"
curl -fsS -X POST "$API_BASE/api/aihr/model/chat" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"prompt":"物业管家处理漏水投诉第一步是什么?"}'
Qdrant 和向量索引可单独 smoke;重建接口会清空旧 embedding 并重建 collection,只用于本地验证或确认维度不一致后的修复:
TOKEN=<登录后 access_token>
API_BASE=${API_BASE:-https://wygj-api.localhost}
curl -fsS http://127.0.0.1:6333/
curl -fsS "$API_BASE/api/knowledge/doc/vector-index-status" -H "Authorization: Bearer $TOKEN"
curl -fsS -X POST "$API_BASE/api/knowledge/doc/rebuild-vector-index" -H "Authorization: Bearer $TOKEN"
浏览器验收仍按 DEMO_ACCEPTANCE.md 的四条关键路径执行。