Commit Graph
45 Commits
Author SHA1 Message Date
admin 6b8c89bcdb feat(mobile): owner identity selector on realtime practice
- default persona falls back to owner-calm; picker below persona cards
  (compact single row), default own community via defaultProfileId,
  storage persistence incl. explicit none, hidden on empty/failure
- profileId passed to realtime session creation when selected
2026-08-05 03:18:50 +08:00
key c16a3e83d7 feat(release): close handler and microphone gaps 2026-07-30 12:01:45 +08:00
key 5027bef32d fix(mobile): support Android system file picker 2026-07-29 23:52:44 +08:00
key cb928edafd fix(mobile): handle file picker cancellation 2026-07-29 02:01:45 +08:00
adminandClaude Opus 5 7096545e82 fix(mobile): translate microphone errors and pre-request permission
实时陪练失败时,getUserMedia 抛出的 Chromium 英文原文会直接透给用户(真机实测见过
"Could not start audio source"),既不可读也不含任何可执行指引。新增
utils/microphone.ts 把权限、设备占用、无设备、非安全上下文四类底层错误翻译成中文
引导;业务层自己抛的中文文案原样透出,未识别的错误回落到原有通用提示。

同时在建会话之前主动申请 RECORD_AUDIO,并在 manifest 显式声明该权限。

需要说明:此权限预申请是防御性的。真机核查 RECORD_AUDIO 已授予、APK 本就声明该权限、
实时链路可正常跑通,先前那次 "Could not start audio source" 是麦克风被其他应用占用
的瞬时故障,不是权限缺陷。未在"权限未授予"的设备上实测过 WebView 是否会自行弹出
Android 运行时授权框,故此调用在已授权设备上为无害空转;若确实不弹,则它是唯一授权入口。
manifest 声明同样只为防未来模块调整导致权限丢失。

新增 6 项单测覆盖错误映射与授权分支(共 168 项通过)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 00:58:40 +08:00
adminandClaude Opus 5 788a2abbe4 fix(mobile): avoid status bar overlap on custom-nav pages
全局 navigationStyle 为 custom,页面需自行避让状态栏,但四处顶部内容仍被状态栏
压住:练习页标题与对话页标题、我的页顶部卡片、问答页头部。

避让不能走 CSS:env(safe-area-inset-top) 在 Android WebView 恒为 0(该值本是
iOS 刘海概念,Chromium 仅在配置 display-cutout 时才上报),uni-app 注入的
--status-bar-height 实测在 App 端同样取不到,两者都会静默回落成 0,造成"构建产物
里改动存在但运行时无效"。改由 utils/safe-area.ts 读
uni.getSystemInfoSync().statusBarHeight,各页面以内联样式绑定 padding-top。

profile 页同时把 min-height 从 100vh 改为 100%:叠加状态栏内边距后 100vh 会
溢出一屏高度产生多余滚动。

真机(vivo V2443A,720x1600,状态栏 72px)像素验证:修复前状态栏下缘 60-80px 带内
有 872 个文字像素,修复后四处均为 0。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 00:58:18 +08:00
adminandClaude Opus 5 5cf7ce5847 feat(practice): run realtime practice on App-Plus through renderjs
App-Plus has no WebRTC or getUserMedia in the logic layer, so realtime
practice was H5-only and the native entry had to advertise a record-then-
transcribe downgrade.

Move the media/WebRTC engine into `realtime-browser-engine.js` and drive it
from `RealtimePracticeAppBridge.vue`, whose renderjs script runs inside the
system WebView where those APIs do exist. The logic layer keeps the
authenticated calls: SDP exchange and `search_knowledge` tool invocation stay
server-proxied, so the access token is never handed to the view layer. Both
sides talk over the renderjs bridge only in session payloads the server
already assembled.

Verified against a real App build (`app-renderjs.js` holds RTCPeerConnection
and getUserMedia; `app-service.js` holds the SDP endpoint, renderjs side has
zero hits). Microphone permission, live transcription, remote playback,
foreground/background switching and disconnect fallback still require Android
and iOS device verification.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 23:58:10 +08:00
admin acd5fd3a6d fix(practice): generate replies from coach hints 2026-07-25 15:44:45 +08:00
admin 2b3c37677d fix(mobile): prioritize practice actions above guidance 2026-07-25 13:17:32 +08:00
admin fa9d6da975 feat(practice): streamline pilot content operations 2026-07-25 12:51:39 +08:00
admin 35b37b07f7 feat(practice): server-owned realtime personas with knowledge tool calling
- AihrRealtimePersonaRegistry whitelist: owner-calm (default), owner-impatient,
  digital-mentor (search_knowledge); persona binds default voice
- /realtime/session assembles session.update server-side (instructions/tools);
  browser forwards payload verbatim; Redis session record 30min with sliding renewal
- /realtime/tools/invoke validates login identity + Redis session ownership +
  persona tool whitelist, then read-only searchAuthorized; per-account rate limits
- source=realtime skips sop review and knowledge-gap persistence (Beta no-persist)
- frontend: persona cards replace 56-voice picker; serialized tool-call chain with
  soft-landing fallback
2026-07-25 11:13:04 +08:00
admin c9d2012ec1 feat(aihr): finalize practice growth and access boundaries 2026-07-25 00:42:19 +08:00
admin faa2a77e9a feat(practice): complete five-position training operations 2026-07-24 00:26:27 +08:00
admin 067cc30d80 feat(aihr): complete M3 protected practice replay 2026-07-23 22:21:43 +08:00
admin 927458b9e0 feat(aihr): harden M0-M2 mobile training flows 2026-07-23 21:18:13 +08:00
admin 0f5c2e8667 feat(mobile-app): prepare native app packaging 2026-07-23 14:40:23 +08:00
admin 4b31848e3d fix(aihr): harden broadcast and mobile assistant flows 2026-07-23 03:35:36 +08:00
admin 455267cf6f feat: add realtime practice voice selector 2026-07-22 12:24:46 +08:00
admin 87772cc64c feat: add qwen realtime practice beta 2026-07-22 09:29:39 +08:00
admin 578592b21d fix(mobile): flex-center pill buttons and fix learning task card layout
- learning: task-list/snippet-list use column direction (row squeeze caused
  one-char-per-line vertical text in today-task cards)
- learning/profile: fold-toggle flex-centered
- login: code-button flex-centered
- practice: transcript-toggle / bubble-action / style-chip flex-centered
- questions: filter-chip flex-centered
- sop: modal-close flex-centered with 32px hit area
- web-ai: bubble-action flex-centered
2026-07-20 09:03:58 +08:00
admin c47bf748cb fix(mobile): replace emoji glyphs with uni-icons and flex centering app-wide
- ChatComposer panel contract: callers now pass uni-icons type names
  (image/sound/list/help/checkmark) instead of emoji
- voice playback buttons: sound icon + pulse animation, no more 🔊/◼ chars
- practice recent list: rare symbols ⌕⌁◉ (tofu risk) -> wallet/gear/chatbubble
- sop resource icon ▶/文 -> 视/文 character badges
- back arrows: 22 char-based ← -> uni-icons back across 21 pages
- line-height centering -> flex in 8 spots (back buttons, media-remove,
  turn-voice capsule, option-marker, text-button, play-question)
2026-07-19 20:16:05 +08:00
admin 064816a784 feat(knowledge): add short-term ask memory 2026-07-18 21:22:49 +08:00
admin 68d5600534 feat(speech): add role-aware emotional TTS profiles 2026-07-18 18:27:14 +08:00
adminandClaude Fable 5 d5ea4b5451 feat(mobile): restore two old-H5 interaction loops in chat form
旧 H5 vs uniapp 逐功能盘点(客户要求'html 版本逻辑保持')后确认的
两个交互缺口,以会话形态补齐:

1. 学练闭环:总结卡底部新增「去练一遍」(旧版'开始跟读'),
   关卡后直达练页预习视图,学完话术立刻练。
2. 建议采用:老师傅提示气泡新增「用这句话回复」(旧版'建议回复'
   的真实数据版),ChatComposer 暴露 setDraft(text)——填入输入框并
   切键盘模式,员工可修改后发送;对打字困难的老年员工是关键路径。

盘点其余结论:旧版功能全部已迁移或被更优实现替代;
团队短板热力图为写死演示数据,真实版记 P2(需后端维度聚合);
演示角色切换/假数据脚手架确认不迁。

验证:本地+生产 E2E——总结卡→去练一遍→预习视图;
对练→老师傅提示→用这句话回复→输入框回填→发送进入下一轮。
发布备份 h5-before-$TS。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 11:29:05 +08:00
adminandClaude Fable 5 a90f241def fix(mobile): overnight audit round — IA cleanup, internal codes, exam guard
夜间自迭代体检(生产四tab+7子页,截图+console+接口+文案标志采集)
发现三类问题,本轮修复:

1. 信息架构(采纳用户建议):今日页「我的地图」四宫格三项与底部tab
   重复(问/练),仅学习中心/工作上报有增量 → 整块从今日页移除,
   「学习中心/我的训练概况/工作上报」下沉到「我」页新「常用功能」组
   (图标+标题+说明行,与我的积分同列);今日页保留小贴士条,
   页面高度显著缩短、不再与tab栏功能重复。

2. 内部编码泄漏:派发 reason 里的调度批次码(AUTO22-20260717
   PILOT-04)在今日「今日安排」、练页「最近练过」、学习中心
   「昨日错题重练」三处原样示人 → 新增 services/text.ts
   stripInternalCodes(剥前缀码保留人话,整行为码则回退默认文案),
   三处渲染点统一接入。

3. 功能不通:直接访问 /pages/user/exam/index(无id)会请求
   /api/aihr/mobile/exams/0 → 服务端500 → load() 增加 id 守卫,
   显示「请从学习中心·考试任务进入」且不再发请求。

同时:今日「打字问」描述改为不换行文案(原两行文案窄列截断)。

验证:本地7项断言全过;生产复核 map removed/code clean/
profile entries/exam guard/exams|0 not fired 全 true。
发布备份 h5-before-20260718055449。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 05:56:15 +08:00
adminandClaude Fable 5 9d7d621300 feat(mobile): rebuild practice session as WeChat-style chat (batch 2)
对练进行中(practiceView=active)改为微信式会话,复用问页同款形态;
预习(场景卡/最近练过/每日三题)与评分/满意度视图保持不变,
start/turn/finish/求助/风格重生成/幂等/红线/满意度脚本逻辑零改动。

ChatComposer:新增 panelItems 属性(自定义⊕面板项+panel事件),
sop 页默认面板不受影响。

practice/index.vue:
- 会话视图:固定铺满窗口区;头部=场景名+第N/3轮+情绪/信任细条+红线提示
- 业主台词=语音优先气泡(TTS预合成+时长+未读红点+转文字/收起,
  TTS不可用回退文本);我的回复右侧粉色气泡;老师傅提示/求助SOP=
  蓝色教练气泡(带播报/引用来源);提交中「业主回应中…」系统气泡
- 风格chips(再严肃/再温柔/更细致/更专业)横排贴输入条上方
- 输入条:按住说话松开即发送(转写→带audioOssId直接提交回合),
  键盘切换,⊕面板=选音频转文字/求助SOP/结束评分(结束评分随
  canFinishPractice置灰)
- 错题重说(红线)、退避回滚(提交失败恢复对话)原逻辑保留

验证:
- 本地全链路:开始练习→业主语音气泡6"+红点→转文字→键盘回复→
  老师傅提示+4风格chips→风格调整→⊕求助SOP气泡→第二轮→
  ⊕结束评分→评分74+老师傅建议+满意度,8张截图目检
- 生产冒烟:语音气泡+红点+按住说话+老师傅提示+风格chips全就位
- H5已发布(备份 h5-before-20260718052458);冲突表已更新

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 05:26:28 +08:00
adminandClaude Fable 5 a4bbfc2222 fix: stop snowflake ossId precision loss and daily-drill audio identity mismatch
线上现象:对练页录音转写后提交回应,报「录音不属于当前账号,请重新录音后提交」。

根因A(前端,截图直接原因):OSS 编号是雪花 ID(如 2078204068457525249),
超出 JS Number 安全整数范围,后端按 RuoYi 规范序列化为字符串,但前端 4 处
用 Number() 强转(对练 ASR、每日题 ASR、每日题恢复列表、候选人面试 ASR),
精度丢失成 …5200,后端按错误 oss_id 查归属 COUNT=0 → 误报。
生产铁证:同一暂存行,正确 id 查得 1 行,JS 强转后的 id 查得 0 行;
用损坏 id 提交 turn 复现原报错,用字符串正确 id 提交成功。

修复A:speech.ts 新增 normalizeOssId(纯字符串校验透传,禁止 Number 强转),
4 处调用点改为字符串保存,practice/candidate 服务签名与状态类型放宽为
number|string(types/api.ts 本就是 number|string,Jackson 字符串转 Long 无损)。

根因B(后端,潜伏):answerDailyDrill 用组织 extPartyId(如 1003)做录音
归属身份校验,而暂存写入的是登录手机号——每日题语音提交必失败。
修复B:新增 validateAudioOwnershipByUser,按服务端登录 owner_user_id
(与暂存同源、不可伪造)校验,对练路径(身份一致)保持原校验不变。

发布与验证:
- H5 已发布(备份 /opt/wygj/backups/h5-before-20260718035416)
- 后端 jar 已发布重启(备份 /opt/wygj/app/ruoyi-admin.jar.bak-20260718035552),
  15s 恢复,重启后对练 turn+字符串 ossId 生产复核通过
- 每日题语音路径为逻辑级+数据级验证(该账号今日无待训练每日题,
  业务级复验待下一次每日题窗口)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 03:57:47 +08:00
admin 6bdc86e3fc feat: restore learning feedback and knowledge capabilities 2026-07-18 00:50:11 +08:00
admin eacf1a0aea feat(mobile): align employee practice screens for release 2026-07-15 11:23:08 +08:00
admin 857092c2c6 fix(mobile): align practice position label 2026-07-14 20:35:28 +08:00
admin 4d4d911bad fix(aihr): add semantic daily drill scoring fallback 2026-07-14 15:53:04 +08:00
admin 8bb43a2394 fix(aihr): align task labels and training duration 2026-07-14 14:15:02 +08:00
admin 9c35949984 fix(aihr): persist daily drill scores 2026-07-14 11:35:57 +08:00
admin 9bbfd575a3 feat(aihr): add voice answers to daily drills 2026-07-14 05:44:26 +08:00
admin d3552cc22d feat(aihr): add pilot satisfaction evidence loop 2026-07-14 04:13:02 +08:00
admin f60176c196 fix(mobile): align practice prep with figma 2026-07-14 03:01:26 +08:00
admin 87360a25d3 feat(aihr): align figma pages for release 2026-07-14 02:04:36 +08:00
admin c66fc4e4b0 feat(mobile): finish employee app page polish 2026-07-11 18:59:30 +08:00
admin ee396d1e7a feat(mobile): 重做员工端首页、问答和训练页视觉
统一员工端 tabBar、共享卡片和三大核心页面的视觉基础,同时保持现有移动端业务流程不变。补充 H5 输入兼容、页面结构和训练回滚行为的回归测试。
2026-07-11 01:13:14 +08:00
admin 61a26fc543 fix(mobile): align practice scene copy with task context 2026-07-09 22:10:31 +08:00
admin 8f73cb0c84 fix(mobile): require employee position before user flow 2026-07-09 17:09:26 +08:00
admin 4ef388873b feat(mobile): add voice transcription to practice 2026-07-09 13:41:48 +08:00
admin 04405b5e11 fix(mobile): reset page scroll on route entry 2026-07-09 13:34:24 +08:00
admin f517cbd2b5 fix(mobile): carry today task into practice 2026-07-09 13:28:52 +08:00
admin 678543e8a5 feat(aihr): complete uni-app role workflows 2026-07-09 10:42:20 +08:00