18 KiB
物业AI人力资源系统 MVP 本地启动
当前仓库
- 后端:
backend,来自dromara/RuoYi-Vue-Plus的5.X分支 - 管理端前端:
frontend,来自CrazyLionCat/plus-ui的5.X分支 - 用户侧前端:
mobile-uni,uni-app Vue3 H5 工程;旧mobile仅保留为 MVP 演示兜底
本地入口与依赖端口
- 管理端前端:
https://wygj-admin.localhost/ - uni-app 用户侧:
https://wygj-mobile-uni.localhost/h5/ - 后端:
https://wygj-api.localhost/ - 固定端口仅用于显式 fallback:
PORTLESS=0 ./scripts/dev.sh时后端回退http://127.0.0.1:8080/,旧移动端回退http://127.0.0.1:5174/h5/user - MySQL:
127.0.0.1:13306,数据库ry-vue,账号root/root - Redis:
127.0.0.1:16379,密码ruoyi123 - MinIO API:
http://127.0.0.1:9000,Console:http://127.0.0.1:9001,账号ruoyi / ruoyi123,默认 bucketruoyi - Qdrant REST:
http://127.0.0.1:6333,默认 collectionaihr_knowledge - 服务端资料导入根目录:
./.data/import
portless 本地入口
本机开发测试优先用 portless 访问稳定域名,避免继续记固定端口:
- uni-app 用户侧:
https://wygj-mobile-uni.localhost/h5/ - 管理端:
https://wygj-admin.localhost/ - 后端 API:
https://wygj-api.localhost
从根目录一次性启动本地依赖、后端、管理端和 uni-app 用户侧:
./scripts/dev.sh
./scripts/dev.sh 默认通过 portless 启动后端、管理端和 mobile-uni,并由 Docker 启动 MySQL/Redis/MinIO/Qdrant。管理端 Vite 代理读取 frontend/.env.development 的 VITE_APP_PROXY_TARGET=https://wygj-api.localhost,mobile-uni Vite 代理默认指向 https://wygj-api.localhost,都不依赖固定 8080。如需单独启动后端,可执行:
portless run --name wygj-api ./scripts/dev-backend.sh
重复启动或切换分支时优先使用 ./scripts/dev.sh restart,停止使用 ./scripts/dev.sh stop。脚本会递归终止 portless 包装进程及其 Java/Vite 子进程,避免旧后端脱离后继续占用 MySQL 连接池;进程树回归可用 bash scripts/tests/process-tree.test.sh 验证。
也可以只让 portless 按根目录 portless.json 启动前端工程:
portless
旧 mobile/ 只在显式 PORTLESS=0 ./scripts/dev.sh 时作为固定端口兜底启动;后端开发测试优先看 wygj-api.localhost,管理端开发测试优先看 wygj-admin.localhost,新用户侧开发测试优先看 wygj-mobile-uni.localhost。
Qdrant 默认本地无需配置;远端或自定义 collection 可用 AIHR_QDRANT_URL、AIHR_QDRANT_COLLECTION、AIHR_QDRANT_API_KEY 覆盖。服务端资料导入根目录可用 AIHR_IMPORT_ROOT 或 -Daihr.import.root 覆盖。组织人员同步可用 AIHR_ORG_SYNC_BASE_URL 指向外部开放平台 /api/open/v1 前缀,并配置 AIHR_ORG_SYNC_ACCESS_TOKEN 或 AIHR_ORG_SYNC_CLIENT_ID/AIHR_ORG_SYNC_CLIENT_SECRET;业务请求会用 client secret 生成 HMAC-SHA256 hex 签名。移动端手机号登录的短信模板 ID、阿里云 AccessKey、Secret 和短信签名都通过环境变量注入;本地放根目录 .env.local,scripts/dev-backend.sh 会自动加载。若开放平台凭证放在 backend/.env,启动脚本也会加载该文件,并把 client_id/client_secret 映射为组织同步实际读取的 AIHR_ORG_SYNC_CLIENT_ID/AIHR_ORG_SYNC_CLIENT_SECRET。
组织同步写入前先运行只读预检:node scripts/verify-demo-questions.mjs --org-dry-run。dry-run 不检查或变更本地快照表结构,也不写数据库;输出只包含人数、手机号覆盖、脱敏数、疑似乱码数和警告,不输出员工姓名。2026-07-15 当前开放平台数据已满足写入条件:3417 名员工中 3392 人可手机号映射,疑似乱码为 0;仍有 25 人手机号不可用,确认后可用 allowPartialReplace=true 覆盖写入。
正式试点预检必须指定当前批次租户和时间窗,例如:AIHR_PILOT_TENANT_ID=000000 AIHR_PILOT_START_DATE=2026-07-07 AIHR_PILOT_END_DATE=2026-07-10 AIHR_PILOT_STRICT=true ./scripts/demo-check.sh。脚本只接受安全租户编号和 YYYY-MM-DD 日期,只统计目标租户窗口内完成的训练、校准和 SOP 评审;人员先按唯一手机号映射到在职组织快照,完训口径为每人至少 10 次已完成对练。
管理端正式试点 CSV 也必须显式选择同一批次日期。可用真实 API 验证其日期拒绝、CSV 契约和正式身份范围:node scripts/verify-demo-questions.mjs --pilot-export --start-date=2026-07-07 --end-date=2026-07-10。
本地 .env.local 示例:
AIHR_SMS_LOGIN_TEMPLATE_ID=SMS_xxxxxx
ALIYUN_SMS_ACCESS_KEY_ID=xxx
ALIYUN_SMS_ACCESS_KEY_SECRET=xxx
ALIYUN_SMS_SIGN_NAME=物业AI助手
# 演示兜底:非空则不真发短信,验证码固定为该值;dev 默认 123456
AIHR_SMS_DEV_FIXED_CODE=123456
# prod 默认 false;试点期仅在明确接受固定码风险时与上一项同时开启
AIHR_SMS_PROD_FIXED_CODE_ENABLED=false
AIHR_ORG_SYNC_BASE_URL=https://wuye.meihe.cc/api/open/v1
AIHR_ORG_SYNC_ACCESS_TOKEN=
AIHR_ORG_SYNC_CLIENT_ID=
AIHR_ORG_SYNC_CLIENT_SECRET=
AIHR_ORG_SYNC_SIGNING_SECRET=
# 若放在 backend/.env,也可沿用开放平台字段名:
# client_id=dn_xxxxxx
# client_secret=dns_xxxxxx
# 试点成本闸门:超预算时改 false,chat/asr/tts/vision 会停止外发并走现有兜底
AIHR_AI_RUNTIME_ENABLED=true
AIHR_AI_CHAT_ENABLED=true
AIHR_AI_SPEECH_ENABLED=true
application-dev.yml 只保留占位和默认值,不提交真实短信密钥。dev 环境不配阿里云短信也能登录移动端:验证码固定 123456。
启动步骤
在项目根目录执行:
./scripts/dev.sh
./scripts/dev.sh 默认通过 portless 暴露后端、管理端和当前 mobile-uni 用户侧。若要显式使用旧端口调试,可执行 PORTLESS=0 ./scripts/dev.sh,后端入口为 http://127.0.0.1:8080/,管理端入口为 http://127.0.0.1:5173/,旧移动端兜底入口为 http://127.0.0.1:5174/h5/user。
首次启动或需要重建本地 ry-vue MVP 数据库时执行:
./scripts/dev.sh --reset
--reset 会删除并重建本地 MVP 数据库,只用于本地开发环境。
默认登录
- 租户:
000000 - 管理员:
admin / admin123 - 测试账号:
test / 666666、test1 / 666666
品牌资源
- 页面标题:
物业AI人力资源系统 - 侧栏 Logo:
frontend/src/assets/logo/logo.png
已验证的基础链路
- MySQL、Redis 与 MinIO 容器健康检查通过
- Qdrant 容器随本地开发编排启动,供 SOP 知识库向量召回使用
ry_vue_5.X.sql、ry_job.sql、ry_workflow.sql已导入aihr_knowledge_mysql8.sql、aihr_model_mysql8.sql已导入;本地库含住宅 SOP seed 片段与模型配置表aihr_practice_mysql8.sql已导入;移动端员工训练记录落aihr_practice_session,用于训练历史、主管待复盘列表和能力画像聚合aihr_interview_result_mysql8.sql已纳入 reset 脚本;AI 面试评分完成后结果落aihr_interview_resultaihr_candidate_material_mysql8.sql已纳入;候选人端补充资料文件写sys_oss/MinIO,关系落aihr_candidate_materialaihr_org_snapshot_mysql8.sql已纳入 reset 脚本;组织人员本地 seed(2 个住宅项目 22 人,项目经理/主管/一线三层)支撑演示,外部开放组织系统配置完成后用POST /api/aihr/org/sync拉取company/department/employee快照并覆盖本地aihr_org_snapshot。2026-07-15 生产已完成该配置和覆盖同步,线上快照为 3417 名员工。- 组织同步生产默认关闭
aihr.org-sync.store-display-fields,不把外部姓名/部门写入或返回组织人员展示快照;开发环境显式打开该开关仅用于 Demo。项目范围、岗位和外部主体 ID仍用于权限与身份映射。 - 本地组织 seed 带演示手机号,可用
13900000103验证员工端自动识别物业管家岗位,用13900000202验证主管端项目范围 - SOP 知识库支持
.txt/.md/.markdown/.pdf/.doc/.docx/.xls/.xlsx/.ppt/.pptx上传到 MinIO 后解析入库,接口为POST /api/knowledge/doc/upload,单文件上限 100MB;管理端上传请求单独放宽到 180s,PDF 解析/归类/向量化较慢时不要改全局 axios 超时。资料处理中心异步接口另支持.zip(≤500MB),后台安全解压后逐文件入队;最多 1000 个子文件、解压总量 ≤2GB,不支持嵌套 ZIP - 视频(
.mp4/.mov/.avi/.mkv/.webm/.m4v,≤500MB、≤60 分钟)只走资料处理中心批量导入(异步队列):ffmpeg 抽音轨分段调 asr 转写 + 抽关键帧调 vision 提取画面文字,合并后归类切片入库,片段带[mm:ss]时间戳;依赖服务器安装 ffmpeg/ffprobe(macOSbrew install ffmpeg,Linuxapt install ffmpeg) - 服务端目录导入接口为
POST /api/knowledge/doc/import-local-task,只读取导入根目录下的相对目录,后台逐文件复用同一上传解析链路;POST /api/knowledge/doc/import-tasks/{id}/cancel可取消运行中任务;POST /api/knowledge/doc/import-local保留为同步调试接口。这组接口仅供运维/调试,不在资料处理页提供入口。 - 启用
aihr_model_config.category='vector'的模型配置后,上传会同步写入片段 embedding,并尽力 upsert 到 Qdrant;模型配置页可查看 Qdrant 维度、点数和片段向量数,并在维度不一致时重建索引;未配置或 Qdrant 不可用时只走 MySQL Fulltext/seed fallback,不影响检索。 - 后端
ruoyi-admin已完成 Maven 打包,并通过 portless 暴露为https://wygj-api.localhost/ - AIHR 真跑测试必须显式关闭父 POM 的默认跳测:
mvn -f backend/pom.xml -pl ruoyi-modules/ruoyi-aihr -am -DskipTests=false test;普通mvn ... test只适合编译/打包检查。 - 前端依赖已安装,Vite 已通过 portless 暴露为
https://wygj-admin.localhost/ - 当前用户侧由
./scripts/dev.sh通过 portless 启动mobile-uni,入口https://wygj-mobile-uni.localhost/h5/;旧移动端兜底仅在PORTLESS=0调试时启动到5174 - 移动端手机号登录页已接
/resource/sms/code与/auth/mobile/sms-login;未配置真实ALIYUN_SMS_ACCESS_KEY_ID、ALIYUN_SMS_ACCESS_KEY_SECRET、ALIYUN_SMS_SIGN_NAME、AIHR_SMS_LOGIN_TEMPLATE_ID时不会发送阿里云短信;手机号不存在时会自动注册为app_user - 移动端员工端“开始训练”已复用
/api/train/practice/start、/turn、/finish;移动端请求需带登录返回的Authorization与clientid;完成后主管端完训人数、“待复盘对练”计数、复盘列表、复盘详情、员工训练历史和能力画像会变化 - 移动端候选人端“开始面试/面试练习”已复用
/api/recruit/interview/start、/answer、/finish;“补充资料”需带移动端Authorization与clientid,上传后写sys_oss和aihr_candidate_material,管理端/recruit/interview可审核为已通过/已驳回 /dev-api/auth/tenant/list与/dev-api/auth/code已通过前端代理返回200000000 / admin / admin123已通过真实加密登录接口返回access_token
Qdrant 单独检查:
curl -fsS http://127.0.0.1:6333/
登录后可检查向量索引状态:
TOKEN=<登录后 access_token>
curl -fsS https://wygj-api.localhost/api/knowledge/doc/vector-index-status -H "Authorization: Bearer $TOKEN"
线上管理端静态发布
线上根站由 Caddy 从服务器 /opt/wygj/www 提供;同一目录下的 /h5 是移动端静态资源。只改管理端静态资源时无需重启后端,但必须先备份整个目录,并且同步根目录时不能使用 --delete,以免删除移动端资源。
npm --prefix frontend run build:prod
ssh YCWY 'ts=$(date +%Y%m%d%H%M%S); mkdir -p /opt/wygj/backups; cp -a /opt/wygj/www /opt/wygj/backups/www-$ts; echo /opt/wygj/backups/www-$ts'
rsync -az frontend/dist/ YCWY:/opt/wygj/www/
curl -k -s https://peilian.njzhmj.top/ | sed -n '1,20p'
发布后以管理员真实会话回归受影响页面;如需核对指定资源,可比较本地构建文件和远端对应文件的 SHA-256。该流程不发布后端、不迁移数据库,也不覆盖 /opt/wygj/www/h5。
线上移动端静态发布
线上 peilian.njzhmj.top 由 Caddy 服务,/h5* 映射到服务器 /opt/wygj/www/h5,并 fallback 到 /h5/index.html。只改移动端静态资源时无需重启后端。
npm --prefix mobile-uni run build:h5
ssh YCWY 'ts=$(date +%Y%m%d%H%M%S); mkdir -p /opt/wygj/backups; cp -a /opt/wygj/www/h5 /opt/wygj/backups/h5-$ts; echo /opt/wygj/backups/h5-$ts'
rsync -az --delete mobile-uni/dist/build/h5/ YCWY:/opt/wygj/www/h5/
curl -k -s https://peilian.njzhmj.top/h5/ | sed -n '1,20p'
发布前先运行只读产物检查,记录 commit、管理端/H5/后端 hash;它不会连接 SSH、同步文件或重启服务:
./scripts/release-preflight.sh
RELEASE_REMOTE_URL=https://peilian.njzhmj.top ./scripts/release-preflight.sh
# 发布后核验线上主资源是否与当前本地产物一致
RELEASE_REMOTE_URL=https://peilian.njzhmj.top RELEASE_VERIFY_REMOTE_MATCH=true ./scripts/release-preflight.sh
# 同时通过 SSH 校验线上后端 jar;默认使用本机 SSH alias YCWY;比较 ruoyi-aihr 模块内容,避免 ZIP 打包时间戳造成误报
RELEASE_REMOTE_URL=https://peilian.njzhmj.top RELEASE_VERIFY_REMOTE_MATCH=true RELEASE_VERIFY_REMOTE_BACKEND=true ./scripts/release-preflight.sh
RELEASE_VERIFY_REMOTE_BACKEND=true 必须与 RELEASE_VERIFY_REMOTE_MATCH=true 同时使用;预检会同时打印整包 jar SHA-256 和 ruoyi-aihr 模块内容 SHA-256,实际匹配以模块内容 hash 为准。远端后端默认核对 /opt/wygj/app/ruoyi-admin.jar,如发布路径不同可通过 RELEASE_REMOTE_BACKEND_PATH 覆盖;路径必须是安全的绝对路径。
带 RELEASE_REMOTE_URL 时,预检同时校验租户接口 JSON 的业务 code=200;HTTP 200 但业务返回 401/405 会判定失败。
发布时必须保留 preflight 输出、远端备份目录和发布后浏览器回归结果;回滚优先使用对应备份目录恢复,再重启后端服务,不能直接覆盖当前线上目录而不留证据。
MVP 页面验证
登录后侧栏应只展示以下入口:
- 首页:
/index - AI面试:
/recruit/interview - 三角色对练:
/train/practice - 案例沉淀:
/knowledge/cases - SOP知识库:
/knowledge/sop - 资料处理:
/knowledge/processing - 系统设置-模型配置:
/system/model
若依默认菜单如“系统管理 / 租户管理 / 系统监控 / 系统工具 / 测试菜单”在当前 MVP 阶段应保持隐藏。
MVP 演示流验证
当前已跑通管理端五个本地演示流和移动端员工训练闭环:
- AI面试:进入
/recruit/interview,点击“生成题目” → 输入真实回答或“填满参考回答” → “完成评分”,应看到新增面试记录;配置 chat 模型时题目和评分都来自真实模型,未配置时使用本地 Rubric。 - 三角色对练:进入
/train/practice,点击“开始对练” → 完成两轮真实或参考回复 → “结束并评分”,应看到“已完成闭环”“导师改写”和新增对练记录。 - 案例沉淀:进入
/knowledge/cases,上传真实语音 → “AI 整理” → “送审” → “入库”,应看到“已完成闭环”和新增案例记录;上传必须先完成 ASR 转写。 - SOP知识库:进入
/knowledge/sop,可上传 txt/md/PDF/Word/Excel/PPT 文档入库;点击“检索” → “生成训练题”,应看到“已完成闭环”、命中数据库 SOP 原文片段和训练题;数据库不可用时页面回退 seed。 - 资料处理:进入
/knowledge/processing,应看到资料总量、解析任务表、处理链路、规则与风险;页面只保留“批量导入”和“刷新”,不应出现“选择目录”“服务端导入”或目录导入任务面板。批量导入走异步队列:提交即返回,页面出现“本次批量上传”进度面板(排队/加工中/完成/失败 + 单条重试),后台 worker 并发 2 逐条解析入库;支持多文件和 ZIP,暂存目录默认./.data/staging(aihr.upload.staging覆盖)。 - uni-app 员工端:进入
https://wygj-mobile-uni.localhost/h5/#/pages/user/today/index,手机号登录(dev 验证码固定123456)。今日页进入问师傅、练习、案例素材和个人页;练习页应能完成开始练习、提交回应、结束评分、每日三题提交,个人页同步训练历史和成长证据包。每日三题正式按组织快照hire_date判断入职三个月窗口;本地 Demo 若快照尚无该字段,仅由dev/localprofile 且application-dev.yml的aihr.practice.allow-legacy-daily-drill-fallback=true启用训练次数回退,生产 profile 即使误传环境变量也强制关闭。 - 移动端登录后若组织快照接口返回
401/403,只降级为手动岗位确认,不应清除手机号登录态;岗位确认页仍需允许员工选择“生活顾问”后继续进入业务页。 - uni-app 主管端:进入
https://wygj-mobile-uni.localhost/h5/#/pages/supervisor/index/index,应看到团队概览、团队画像、团队预警、指派专项、待复盘和复盘详情;从团队画像派专项后,最近专项应立即回读新记录。 - uni-app 候选人端:进入
https://wygj-mobile-uni.localhost/h5/#/pages/candidate/index/index,手机号登录(dev 验证码固定123456)→ “开始面试/面试练习”完成答题评分;“补充资料”选择 PDF/Word/图片后上传,应看到资料状态。Codex 内置浏览器不支持本地文件选择时,用真实 HTTP multipart smoke 代替浏览器文件选择。 - 真 LLM 激活:在
/system/model给供应商填 api_host/api_key 并启用category=chat模型后,三角色对练的客户回复与评分即为真实 LLM 生成;再启用category=asr/tts(如硅基流动 SenseVoice/CosyVoice2)语音路径生效。未配置时全链路自动回退 seed。
演示前可先跑最小预检:
./scripts/demo-check.sh
完整演示脚本与录屏兜底见 DEMO_ACCEPTANCE.md。