// 已读取AGENTS.md import * as fs from 'fs'; import * as path from 'path'; /** * 第九十一批:语音自我介绍三端一致性。 * 背景:管理端「真人语音包核听」曾是 3 秒假播放(文案写死 16s), * 入驻申请页也没有录音入口,导致审核端永远听不到真人语音。 */ describe('第九十一批语音介绍三端一致性闸门', () => { const root = path.resolve(__dirname, '../../'); const audit = fs.readFileSync( path.join(root, 'admin/arco-design-pro-vite/src/views/companion/audit/index.vue'), 'utf-8' ); const apply = fs.readFileSync(path.join(root, 'pwuniapp/pages/expert/apply.vue'), 'utf-8'); it('审核页按真实 voiceIntroUrl 播放,未上传时禁用并标记', () => { expect(audit).toContain('record.voiceIntroUrl'); expect(audit).toContain('new Audio(url)'); expect(audit).toContain('未上传'); expect(audit).not.toContain('播放中 16s...'); }); it('入驻申请页提供录音入口并在提交成功后上传语音', () => { expect(apply).toContain('uni.getRecorderManager()'); expect(apply).toContain('uploadVoiceIntro'); expect(apply).toContain('applied.id'); expect(apply).toContain('duration: 60000'); }); it('录音时实时读秒并在 60 秒自动停止', () => { const workspace = fs.readFileSync(path.join(root, 'pwuniapp/pages/expert/workspace.vue'), 'utf-8'); for (const src of [apply, workspace]) { expect(src).toContain('startVoiceTimer'); expect(src).toContain('stopVoiceTimer'); expect(src).toContain('setInterval'); expect(src).toContain('voiceSeconds.value >= 60'); expect(src).toContain('recorderManager.stop()'); } expect(apply).toContain('剩余 ${Math.max(0, 60 - voiceSeconds.value)}s'); expect(workspace).toContain('剩余 ${Math.max(0, 60 - voiceSeconds)}s'); }); const scanSensitive = (dir: string): string[] => { const hits: string[] = []; for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { const full = path.join(dir, entry.name); if (entry.isDirectory()) hits.push(...scanSensitive(full)); else if (/\.(vue|js)$/.test(entry.name)) { const text = fs.readFileSync(full, 'utf-8'); if (/语音房|连麦|开麦/.test(text)) hits.push(full); } } return hits; }; it('小程序页面文案不出现语音房/连麦/开麦等审核敏感词', () => { const hits = scanSensitive(path.join(root, 'pwuniapp/pages')); expect(hits).toEqual([]); }); });