Component({ properties: { // 语音消息数据 voiceData: { type: Object, value: {}, observer: 'onVoiceDataChange' }, // 是否为自己发送的消息 isSelf: { type: Boolean, value: false }, // 消息ID messageId: { type: String, value: '' } }, data: { // 播放状态 isPlaying: false, // 波形数据 waveformData: [], // 语音信息 voiceUrl: '', voiceDuration: 0 }, lifetimes: { attached() { this.initComponent(); }, detached() { this.cleanup(); } }, methods: { // 初始化组件 initComponent() { // 生成波形数据 this.generateWaveform(); // 获取全局音频上下文 const app = getApp(); this.audioContext = app.globalData.audioContext || wx.createInnerAudioContext(); // 注册音频事件 this.setupAudioEvents(); }, // 语音数据变化处理 onVoiceDataChange(newData, oldData) { if (!newData || JSON.stringify(newData) === JSON.stringify(oldData)) { return; } this.setData({ voiceUrl: newData.url || '', voiceDuration: newData.duration || 0 }); // 重新生成波形 this.generateWaveform(); }, // 设置音频事件监听 setupAudioEvents() { if (!this.audioContext) return; this.audioContext.onPlay(() => { if (this.isCurrentAudio()) { this.setData({ isPlaying: true }); } }); this.audioContext.onPause(() => { if (this.isCurrentAudio()) { this.setData({ isPlaying: false }); } }); this.audioContext.onEnded(() => { if (this.isCurrentAudio()) { this.setData({ isPlaying: false }); } }); this.audioContext.onError((err) => { console.error('语音播放错误:', err); if (this.isCurrentAudio()) { this.setData({ isPlaying: false }); wx.showToast({ title: '播放失败', icon: 'none' }); } }); }, // 检查是否为当前音频 isCurrentAudio() { return this.audioContext && this.audioContext.src === this.data.voiceUrl; }, // 切换播放状态 togglePlay() { if (!this.data.voiceUrl) { wx.showToast({ title: '语音地址无效', icon: 'none' }); return; } try { if (this.data.isPlaying) { this.audioContext.pause(); } else { // 停止其他正在播放的音频 if (this.audioContext.src !== this.data.voiceUrl) { this.audioContext.src = this.data.voiceUrl; } this.audioContext.play(); } } catch (error) { console.error('播放语音失败:', error); wx.showToast({ title: '播放失败', icon: 'none' }); } }, // 生成波形数据 generateWaveform() { const duration = this.data.voiceDuration || 1000; const barCount = Math.min(Math.max(Math.floor(duration / 200), 8), 30); // 8-30个波形条 const waveformData = []; for (let i = 0; i < barCount; i++) { // 生成随机高度,模拟真实波形 const height = Math.random() * 60 + 20; // 20-80%的高度 waveformData.push(height); } this.setData({ waveformData }); }, // 清理资源 cleanup() { // 如果当前正在播放,停止播放 if (this.data.isPlaying && this.audioContext) { try { this.audioContext.stop(); } catch (e) { // 忽略停止错误 } } } } });