- TTS /tts/asr: convert non-WAV (AAC/MP3) to WAV before whisper transcription
- share.vue: only create share record if no cached shareCode exists
(prevents duplicate share records on every page load)
- Backend: wrap AI call in try/catch, throw HttpException(503)
with msg 'AI 服务暂时不可用,请稍后重试'
- Backend: AllExceptionsFilter preserve original error message
for non-HttpException errors
- Frontend: handle string/object res.data, show statusCode
as fallback when message is unavailable
- Change recorder format from mp3 (8kHz) to aac (22kHz) for better
whisper ASR accuracy
- Move recorder.onStop binding before recorder.stop() to prevent
race condition (onStop may fire before handler is registered)
- Backend: add Logger, log ASR errors instead of silent catch {}
- Backend: change default extension from .mp3 to .aac
- Split checkAndDeductInterview into checkInterview (read-only) and
deductInterview (deduction only)
- Restructure interview.create(): check gravity -> AI call -> deduct on success
- If AI call fails, gravity is never deducted
- Keep old checkAndDeductInterview for backward compatibility
Add lastLoginAt, lastLoginIp, lastLoginLocation to User schema. recordLogin() method called from all 5 login flows (phone, email, wx, password, register). Exposed in safeUser so info endpoint returns login metadata.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
- Backend getUsers: add wxOpenid to regex search
- Backend getAdmins: return gravity, plan, wxOpenid, email fields
- Frontend admin tab: show full user info (ID copy, email, gravity, plan)
- Frontend search result: show complete user details like user list rows
- Backend: add email + _id to filter in getUsers() for fuzzy search
- Frontend: show full MongoDB _id in user row with tap-to-copy
- Search placeholder updated to mention email/ID
- user.schema.ts: convert pre-save from callback(next) to async - fixes
'TypeError: next is not a function' on login (Mongoose 8 compat)
- Tag v1.0.17 for 1.0.18 build cycle
- scripts/seed-test-user.ts: utility to create test accounts
- docs: PROJECT-STATUS v4.9, AGENTS.md version bump
- Add test user test@yzrcloud.cn / 123456 (role: user)
- Replace backup model stepfun-ai/step-3.5-flash with meta/llama-3.1-8b-instruct
(stepfun is a thinking model that uses all tokens on reasoning and
never outputs content, causing all 3 fallthroughs to fail)
- Add retry with doubled max_tokens when primary model returns empty
content (deepseek-v4-flash thinking can exhaust token budget)
- Increase backup timeout to 120s and max_tokens to min 2048
- Move callApi error handling to return null instead of throw for
cleaner fallthrough logic with timeout logging
- verifyAndDecrypt now processes decryption even when signature
verification fails (decryption key is separate from signature key)
- Notify handler uses returnRaw flag to always decrypt resource
- Loud log when pub_key.pem verification fails, directs admin
to download correct public key from merchant platform
New backend module 'interview-review' provides:
- Audio upload (50MB limit, MP3/M4A/WAV/AAC/OGG/MP4/WebM)
- Text transcript submission
- whisper.cpp local ASR integration (tiny + base models)
- AI analysis (4-dimension scoring: logic/expression/professionalism/stability)
- Speech analysis (filler words detection, pace, duration)
- Async processing pipeline with status polling
- Graceful fallback to mock ASR when whisper unavailable
New frontend page 'pages/review/review.vue' with 3 modes:
- List mode: review history with status indicators
- Upload mode: audio file upload or text paste
- Report mode: score radar, dimension bars, analysis details
Docs updated: PROJECT-STATUS.md v4.4, FEATURE-LIST.md v4.2, ROADMAP.md v4.2