Files
prop-ai-hr/AGENTS.md
T

81 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AGENTS.md
## 项目定位
本项目是**帮道 APP**,按“陪练 → 大喇叭+知识学习平台 → 北森对接”三阶段推进。正式验收主线是阶段一试点;后续能力提前发布不等于整体验收。结论须区分生产部署、正式账号/真机验证和严格试点。
## 工程边界
- `backend/` 是 `dromara/RuoYi-Vue-Plus` 的 `5.X` 分支检出。
- `frontend/` 是 `CrazyLionCat/plus-ui` 的 `5.X` 分支检出,只承载管理端。
- `mobile-uni/` 是当前用户侧工程,承载员工端、候选人端、主管端,使用 uni-app Vue3 H5 + App-Plus;原生资源、隐私/签名和真机门禁见 `docs/MOBILE_APP_PACKAGING.md`,旧 `mobile/` 仅保留为 MVP 演示兜底,不再承载新增功能。
- 本项目自己的本地编排放在根目录:`docker-compose.dev.yml`、`scripts/`;运行说明在 `docs/DEV_SETUP.md`。
- 除非确实要接业务模块,不要改上游框架默认配置;本地端口和开关优先放根目录脚本里覆盖。
## 本地运行
- MySQL:`127.0.0.1:13306`,库 `ry-vue`,账号 `root/root`。
- Redis:`127.0.0.1:16379`,密码 `ruoyi123`。
- MinIO:API `127.0.0.1:9000`,Console `127.0.0.1:9001`,账号 `ruoyi / ruoyi123`,bucket `ruoyi`。
- Qdrant:REST `127.0.0.1:6333`,默认 collection `aihr_knowledge`;可用 `AIHR_QDRANT_URL`、`AIHR_QDRANT_COLLECTION`、`AIHR_QDRANT_API_KEY` 覆盖。
- 资料导入根目录:默认 `./.data/import`,由 `scripts/dev-backend.sh` 传入 `aihr.import.root`;也可用 `AIHR_IMPORT_ROOT` 覆盖。
- 本地私密配置:根目录 `.env.local` 已被 `.gitignore` 忽略,`scripts/dev-backend.sh` 会自动加载;阿里云短信密钥只放这里或外部环境变量,不写入 `application-*.yml`。管理端图形验证码本地默认关闭,只有 `AIHR_DEV_CAPTCHA_ENABLED=true` 才开启;该开发开关不进入生产启动。
- 后端默认通过 portless 启动,入口 `https://wygj-api.localhost/`;使用 `portless run --name wygj-api ./scripts/dev-backend.sh` 或 `./scripts/dev.sh`,`PORTLESS=0` 回退 `8080`。管理端代理目标在 `frontend/.env.development`。
- 管理端前端:`./scripts/dev-frontend.sh`,默认走 portless,入口 `https://wygj-admin.localhost/`;显式 `PORTLESS=0` 时回退端口 `5173`。
- 当前用户侧前端:`portless` 启动 `mobile-uni`,入口 `https://wygj-mobile-uni.localhost/h5/`。
- 旧移动端兜底:`./scripts/dev-mobile.sh`,端口 `5174`,只用于回看 MVP 演示壳。
- 重置数据:`./scripts/reset-dev-db.sh`,会删除并重建本地 `ry-vue`。
导入 SQL 必须带 `--default-character-set=utf8mb4`,否则中文昵称可能按错误字符集导入并触发字段长度问题。
## 验证口径
- 前端首页:`https://wygj-admin.localhost/`
- 用户侧首页:`https://wygj-mobile-uni.localhost/h5/`
- 后端接口:`https://wygj-api.localhost/`
- 租户接口:`https://wygj-admin.localhost/dev-api/auth/tenant/list`
- 验证码接口:`https://wygj-admin.localhost/dev-api/auth/code`
- 默认登录:租户 `000000`,管理员 `admin / admin123`。
## 发布口径
- 线上管理端:`https://peilian.njzhmj.top/`,Caddy 服务 `/opt/wygj/www`;该目录包含移动端 `/h5`,发布管理端时先备份整个目录,再 `rsync -az frontend/dist/ YCWY:/opt/wygj/www/`,**不得**对根目录使用 `--delete`。纯管理端静态修复不需要重启后端。
- 线上移动端 H5:`https://peilian.njzhmj.top/h5/`,Caddy 服务 `/opt/wygj/www/h5`。
- 只发布移动端静态资源时,用 `npm --prefix mobile-uni run build:h5` 后备份远端 `/opt/wygj/www/h5`,再 `rsync -az --delete mobile-uni/dist/build/h5/ YCWY:/opt/wygj/www/h5/`;前端静态修复不需要重启后端。
- 原生 App 不复用 H5 静态发布流程;`npm --prefix mobile-uni run build:app` 仅生成 HBuilderX 出包资源,未提供法务 HTTPS 链接、签名或真机验收前不得称为已出包或上架。
- 完整发布收口须按 `docs/DEV_SETUP.md` 运行同时启用远端静态、后端和 schema 的 `release-preflight`;只有三项都通过,才可称当前本地构建已与线上完整包匹配。单纯 H5 资源匹配不等同于完整发布验证。
- `aihr.practice.runtime-schema-bootstrap` / `AIHR_PRACTICE_RUNTIME_SCHEMA_BOOTSTRAP` 仅限本地开发逃生开关,Spring 默认关闭;生产请求只能校验表、列和关键索引,任何 DDL 都必须由正式 SQL 迁移完成,完整预检会拒绝开启该开关的服务。
## 当前业务边界
- 管理端业务路由集中在 `frontend/src/router/index.ts`,覆盖首页、AI 面试、训练运营、问题榜、案例、知识空间、SOP、资料处理、大喇叭、五渠道直通反馈、系统配置、组织权限和成长激励;侧栏过滤在 `frontend/src/layout/components/Sidebar/index.vue`,不要恢复若依默认全量菜单。
- 用户侧只改 `mobile-uni/src/pages/*`;员工、候选人、主管首页分别为 `/pages/user/today/index`、`/pages/candidate/index/index`、`/pages/supervisor/index/index`,旧 `/h5/user|candidate|supervisor|employee|admin` 只做兼容重定向,底栏固定「今日/练/问/我」。“问”统一调用 `/api/aihr/agent/messages|messages/media`,服务端规划意图并按固定策略选择既有工具,客户端不得提交 `toolCode`;旧知识查询仅作底层/兼容。登录端短期会话为 30 分钟/最近 6 轮,原文件/视频经 `/api/knowledge/resources/{attachmentId}/content` 重新鉴权,总结卡失败不兜假数据。全网外发必须先同意,显式记忆先出确认卡,再通过不透明 `draftId` 按 `PRIVATE/COMPANY` 确认;`COMPANY` 仅为 `PENDING`,不得冒充已派单或送达。`aihr_agent_run` 不保存问题、答案或附件,外部知识 API 保持无状态。
- 大喇叭详情追问只让客户端传 `broadcastMessageId`,消息正文、附件文本、租户和身份均由服务端重新校验并加载;撤回、跨租户或非在职员工不得继续使用消息上下文。单条消息最多绑定一个属于当前租户、当前上传人且状态为 `READY` 的公司文件;员工端只返回摘要与受控下载入口,不返回提取全文或原始 OSS 地址。消息/知识回答不得把通用建议包装成当前员工的真实待办,强行动入口只能来自服务端已授权的真实任务数据。
- 直通车固定为总裁、财务、人力、审计、运营五个渠道;业务匿名只隐藏处理端的提交人展示,服务端仍保留内部提交账号供本人查询、幂等和审计。`direct_president/direct_finance/direct_hr/direct_audit/direct_operations` 只处理各自渠道,`superadmin` 可处理全部;当前产品边界只允许一次正式回复,不扩展为多轮聊天、工单、转派或 SLA。
- 术语和数据边界:工作助手承载日常事实与确认式记忆;现有 `/pages/user/report/index`、`/api/aihr/work-report/**` 和 `aihr_work_report` 只承载 CASE/VIDEO/SOP/KNOWLEDGE 四类投稿审核,产品名为“成果投稿”;“今日工作成果”按员工 + 项目 + 自然日从已确认记录确定性聚合,员工页为 `/pages/user/work-results/index`,主管页为 `/pages/supervisor/work-results/index`,默认当日但允许查看历史日期且不得选择未来日期。不要把三条链路合表或自动互写。多项目交互只让用户按项目名称选择,内部项目编码必须由服务端按当前身份复核,不让用户输入编码。
- 不要把三端概括成全模态:员工对练/每日题和问师傅支持文字/语音,问师傅图片/视频只用于本次分析,案例传音频;候选面试支持文字/语音,资料可传文档/图片但图片不参与评分;主管写文字复盘/指派并回听录音。员工对练图像/视频情境、服务录像回放和方言正式验收仍未完成;语音继续复用 `services/speech.ts` 与 `/api/ai/asr`。
- 问题榜奖励只记积分/学习学分,不得擅自增加现金、提现、预算或税务语义;选最佳答案和考试提交必须保持请求幂等。
- 全网 AI 与企业问师傅必须分入口、分来源和分免责声明;提供方仅允许公网 HTTPS,修改地址/密钥后必须连接测试成功才能启用,未配置时明确不可用且不生成假答案。
- 多租户知识平台的有效范围是“租户 + 调用应用绑定 + 主体授权”的交集;不信任客户端传入身份,API_TOKEN 不得进入浏览器或小程序包。生产排序规则以 `aihr_knowledge_info.tenant_id` 为基准,新表最后执行 `aihr_20260718_release_collation_compat_mysql8.sql`。
- 移动端首页接口:`GET /api/aihr/mobile/home/{role}`,当前 `@SaIgnore` 公开只读 seed,用于 H5 首屏 API 优先 + 本地 fallback;后续确定小程序登录后再接移动端 token,不复用管理后台登录态。
- 移动端手机号登录:验证码发送走 `GET /resource/sms/code?phonenumber=...`,登录走 `POST /auth/mobile/sms-login`;短信发送复用 `sms.blends.config1` 阿里云配置。手机号不存在时自动注册 `app_user`,备注为“移动端短信自动注册”。模板 ID 用 `AIHR_SMS_LOGIN_TEMPLATE_ID`,AccessKey/Secret/签名用 `ALIYUN_SMS_ACCESS_KEY_ID`、`ALIYUN_SMS_ACCESS_KEY_SECRET`、`ALIYUN_SMS_SIGN_NAME`,本地放 `.env.local`。`aihr.sms.dev-fixed-code` 非空则验证码固定(dev 默认 `123456`)、不真发短信;prod 默认关闭,试点期必须同时显式设置 `AIHR_SMS_DEV_FIXED_CODE` 与 `AIHR_SMS_PROD_FIXED_CODE_ENABLED=true`,停用时删除固定码并关闭生产开关。
- 移动端员工训练闭环:员工端首页“开始训练”复用 `POST /api/train/practice/start`、`/turn`、`/finish`,请求必须带移动端登录返回的 `Authorization` 与 `clientid`;服务端强制当前 APP 身份和 `mode=mobile`,才会写入 `aihr_practice_session` 并更新主管端首页完训率、“待复盘对练”、员工训练历史和能力画像。APP 身份只能按认证手机号精确匹配 `person_phone`(`/me`、问师傅主体解析同样只走 `activeByMobilePhone`),运营/调度身份只能按 `ext_party_id` 解析;严禁把两种字段混作替代查询键,映射碰撞或不唯一时必须拒绝任务读写。员工历史、画像、成长进度、晋升证据仅可使用该手机号服务端验证得到的受控别名集合;后台不得借 `/api/aihr/mobile/**` 传入组织 `ext_party_id` 读取员工历史、错题、画像、证据、主管复盘或录音;后台只保留 `/api/train/practice/**` 的内容/任务运营,以及服务端固定 `operator:{userId}`、`mode=preview` 的不绑定员工身份预览。主管团队范围只保存外部 ID;旧手机号仅当其唯一对应一个外部 ID,且该外部 ID 也唯一对应一个在职手机号时,才可规范化读取/统计;该相同的失败关闭规则必须用于团队列表、详情、复盘与音频授权。案例项目范围和岗位 SOP 同样复用已验证 APP 主体的精确项目范围,不得以 `person_phone OR ext_party_id` 或管理端组织模糊查询作为后备。`superadmin/hr_operator` 管理端仅可走服务端绑定的 `operator:{userId}`、`mode=preview` 运营预览,忽略客户端员工身份/模式/任务,且预览不得进入员工历史、复盘、成长或试点统计;其他后台身份一律拒绝。主管端复盘详情查 `GET /api/aihr/mobile/practice/reviews/{id}`,标记复盘用 `POST /api/aihr/mobile/practice/reviews/{id}/reviewed`。
- 正式试点 CSV 走 `GET /api/train/practice/export?startDate=YYYY-MM-DD&endDate=YYYY-MM-DD`,起止日必填;训练、校准和 SOP 评审必须按同一窗口、唯一在职组织身份统计,完训定义为每人至少 10 次。CSV 应保留原始校准命中/SOP 可用计数,严格预检用 `AIHR_PILOT_START_DATE`、`AIHR_PILOT_END_DATE` 与 `AIHR_PILOT_STRICT=true ./scripts/demo-check.sh`;不允许用历史 seed、开发身份或四舍五入比率伪造正式试点通过。
- 移动端候选人闭环:候选人端“开始面试/面试练习”复用 `POST /api/recruit/interview/start`、`/answer`、`/finish`;“补充资料”走认证接口 `POST /api/aihr/mobile/candidate/materials`(multipart `file` + `candidateId/candidateName/materialType`)和 `GET /api/aihr/mobile/candidate/materials`,文件先写 `sys_oss`/MinIO,再写 `aihr_candidate_material` 状态 `待审核`。HR 审核复用管理端 `/recruit/interview` 页,接口为 `GET /api/aihr/hr/candidate/materials` 和 `POST /api/aihr/hr/candidate/materials/{id}/review`,状态只用 `待审核/已通过/已驳回`。上传接口不要放进 class-level `@SaIgnore` 的 `AihrMobileController`。
- 后端 API 对接先看 `docs/API_INTEGRATION.md`。三角色对练 `/turn`/`/finish` 使用 `AihrPracticeLlmService`,必须保留“未配置/失败回退 seed”的降级链。
- 对练语音走 `POST /api/ai/asr`(≤5MB multipart)和 `POST /api/ai/tts`(文本≤300字,返回 base64 dataURL);TTS 保留旧 `voice` 字符串,并支持 `voiceProfile={role,voice?,speed?,emotion?}`,当前老师傅/业主/面试官分音色,业主按对练情绪分调整语气与语速。模型走 `aihr_model_config` 的 `asr`/`tts` 类目(`category` 全集:chat/vector/rerank/asr/tts/vision)。移动端 `getUserMedia/MediaRecorder` 不可用或麦克风权限失败时,用隐藏 `audio/*` file input 选择/录制音频后继续走同一 ASR 接口,不要退回只有文字输入。multipart 头部的 filename/contentType 已做 CRLF 清洗,新增外发 HTTP 时同样注意。
- 后端业务代码不要塞进上游 `ruoyi-demo`;自有 API 放在 `backend/ruoyi-modules/ruoyi-aihr`,再接入 `ruoyi-admin`。
- AI 面试页、三角色对练页、案例沉淀页、SOP 知识库页和移动端三端首页已是 API 优先 + 本地 fallback;SOP 知识库优先查 `aihr_knowledge_fragment` 的 MySQL Fulltext,vector 模型和 Qdrant 可用时混合召回,`category=rerank` 模型启用时融合后语义重排(失败保持 RRF 顺序);支持 `.txt/.md/.markdown/.pdf/.doc/.docx/.xls/.xlsx/.ppt/.pptx`、图片 `.jpg/.jpeg/.png/.gif/.webp/.bmp` 及视频 `.mp4/.mov/.avi/.mkv/.webm/.m4v` 上传解析入库。
- 浏览器批量上传走异步队列 `POST /api/knowledge/doc/upload-async`(暂存目录 `aihr.upload.staging` 默认 `./.data/staging`,队列表 `aihr_knowledge_upload_item`,单文件重试);同步接口 `POST /api/knowledge/doc/upload` 只留给 SOP 页单文件即时预览,**不要把重加工逻辑加回同步请求线程**。视频(≤500MB/≤60分钟)只走异步队列,依赖服务器安装 ffmpeg/ffprobe。
- SOP 上传接口是 `POST /api/knowledge/doc/upload`,表单字段为 `file` 和 `category`;当前限制 100MB 内,支持 txt/md/PDF/Word/Excel/PPT 及图片,先写 MinIO/`sys_oss` 再绑定 `aihr_knowledge_attach.oss_id`,同一知识库同名文件会替换旧 fragment。若数据库启用 `category=vector` 的模型配置,会同步调用 OpenAI-compatible `/embeddings`,写入 `embedding_json` 并尽力 upsert 到 Qdrant;配置缺失或外部 embedding 失败才用 `local-hash-v1` 兜底,Qdrant 不可用时保留 MySQL Fulltext/seed fallback。管理端 `uploadKnowledgeDoc` 单接口 timeout 是 180s;遇到约 50s `Broken pipe` 先查浏览器客户端超时,不要改全局 axios。
- 图片视觉 OCR:上传图片时经 `visionRuntime()` 找启用模型(优先 `aihr_model_config.category='vision'`,无则回退 `category='chat'`),把图片编码成 base64 data URL 调 OpenAI-compatible `/chat/completions` 提取文字再切分入库;无可用视觉模型或 OCR 无结果时按「待处理」落库(0 片段),不算失败。视频关键帧用带画面描述的 FRAME_PROMPT(文字+一句场景描述),改 prompt 时别退回纯 OCR。不依赖 Tesseract。
- 向量库状态接口是 `GET /api/knowledge/doc/vector-index-status`,重建接口是 `POST /api/knowledge/doc/rebuild-vector-index`;外部 embedding 成功但 Qdrant collection 维度不一致时不要静默降级,走状态提示和重建。
- 资料处理接口是 `GET /api/knowledge/processing/overview`,直接聚合 `aihr_knowledge_attach`、`aihr_knowledge_fragment` 和 `sys_oss.ext1`;页面只保留“批量导入”,走 `POST /api/knowledge/doc/upload-async`,不要恢复“选择目录”“服务端导入”或目录导入任务面板。`POST /api/knowledge/doc/import-local`、`POST /api/knowledge/doc/import-local-task`、`GET /api/knowledge/doc/import-tasks` 和 `POST /api/knowledge/doc/import-tasks/{id}/cancel` 仅保留为后端运维/调试接口;目录只能是 `aihr.import.root` 下的相对路径。
- `ruoyi-ai` 只按 `docs/RUOYI_AI_INCREMENTAL_MIGRATION.md` 分片迁移到 `ruoyi-aihr`,不要整包搬 `ruoyi-chat`;已落地页面保持真实接口/模型优先与 seed fallback,不能退回静态壳。
- 本项目 AI 表前缀用 `aihr_*`:知识库是 `aihr_knowledge_info/attach/fragment`,问师傅短期会话是 `aihr_knowledge_conversation`,Agent 审计是 `aihr_agent_run`,大喇叭公司文件是 `aihr_broadcast_attachment`,直通车反馈是 `aihr_direct_feedback`,确认式采集是 `aihr_memory_candidate` / `aihr_assistant_capture`(旧项目记录兼容 `aihr_service_memory/version`),上传队列是 `aihr_knowledge_upload_item`,导入任务是 `aihr_knowledge_import_task`,模型配置是 `aihr_model_provider/config`,移动端训练记录是 `aihr_practice_session`,候选人补充资料是 `aihr_candidate_material`,组织人员快照是 `aihr_org_snapshot`(本地 reset 有 Demo seed;生产/试点从 `docs/open-org-sync-api-design-v1.md` 对应开放组织系统同步,入口 `POST /api/aihr/org/sync`)。
## 业务文档
- 索引与范围:`README.md`、`docs/README.md`、`docs/银城员工端APP分阶段实施总纲.md`、`docs/AI陪练完整交付计划-20260724.md`;旧二期计划只作追溯。
- 当前事实与契约:`docs/BRD_IMPLEMENTATION_AUDIT.md`、`docs/BRD_PRODUCTION_MIGRATION_RUNBOOK.md`、`docs/API_INTEGRATION.md`、BRD/TechSpec 与 `docs/FIGMA_DESIGN_INVENTORY.md`。