feat: 用户语音消息支持点击播放
This commit is contained in:
@@ -196,6 +196,40 @@
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.audio-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.play-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 15px;
|
||||
border-radius: 20px;
|
||||
border: none;
|
||||
background: rgba(255,255,255,0.2);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.play-btn:hover {
|
||||
background: rgba(255,255,255,0.3);
|
||||
}
|
||||
|
||||
.play-btn.playing {
|
||||
background: rgba(255,255,255,0.4);
|
||||
}
|
||||
|
||||
.play-icon {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.duration {
|
||||
color: rgba(255,255,255,0.8);
|
||||
}
|
||||
|
||||
.loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@@ -470,6 +504,9 @@
|
||||
try {
|
||||
showLoading();
|
||||
|
||||
// 计算音频时长
|
||||
const duration = Math.round(recordedBuffers.reduce((acc, buf) => acc + buf.length, 0) / 16000);
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('audio', audioBlob, 'recording.wav');
|
||||
if (conversationId) {
|
||||
@@ -489,8 +526,8 @@
|
||||
const data = await resp.json();
|
||||
conversationId = data.conversation_id;
|
||||
|
||||
// 显示消息
|
||||
addMessage('user', '🎵 语音消息');
|
||||
// 显示消息(带音频播放)
|
||||
addMessage('user', audioBlob, duration);
|
||||
addMessage('assistant', data.reply);
|
||||
|
||||
recordStatus.textContent = '点击按钮开始录音';
|
||||
@@ -503,7 +540,7 @@
|
||||
}
|
||||
|
||||
// 添加消息
|
||||
function addMessage(role, content) {
|
||||
function addMessage(role, content, audioDuration = null) {
|
||||
// 移除提示
|
||||
const hint = chatSection.querySelector('.hint');
|
||||
if (hint) hint.remove();
|
||||
@@ -514,16 +551,50 @@
|
||||
|
||||
const msg = document.createElement('div');
|
||||
msg.className = `message ${role}`;
|
||||
msg.innerHTML = `
|
||||
<div class="role">${role === 'user' ? '我' : 'AI'}</div>
|
||||
<div class="content">${content}</div>
|
||||
`;
|
||||
|
||||
// 用户消息可能是音频
|
||||
if (role === 'user' && content instanceof Blob) {
|
||||
const audioUrl = URL.createObjectURL(content);
|
||||
const durationText = audioDuration ? `${audioDuration}s` : '';
|
||||
msg.innerHTML = `
|
||||
<div class="role">我</div>
|
||||
<div class="content audio-content">
|
||||
<button class="play-btn" onclick="playAudio('${audioUrl}', this)">
|
||||
<span class="play-icon">▶️</span>
|
||||
<span class="duration">${durationText}</span>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
msg.innerHTML = `
|
||||
<div class="role">${role === 'user' ? '我' : 'AI'}</div>
|
||||
<div class="content">${content}</div>
|
||||
`;
|
||||
}
|
||||
chatSection.appendChild(msg);
|
||||
|
||||
// 滚动到底部
|
||||
chatSection.scrollTop = chatSection.scrollHeight;
|
||||
}
|
||||
|
||||
// 播放音频
|
||||
function playAudio(audioUrl, btn) {
|
||||
const audio = new Audio(audioUrl);
|
||||
const icon = btn.querySelector('.play-icon');
|
||||
|
||||
audio.onplay = () => {
|
||||
icon.textContent = '🔊';
|
||||
btn.classList.add('playing');
|
||||
};
|
||||
|
||||
audio.onended = () => {
|
||||
icon.textContent = '▶️';
|
||||
btn.classList.remove('playing');
|
||||
};
|
||||
|
||||
audio.play();
|
||||
}
|
||||
|
||||
// 显示加载
|
||||
function showLoading() {
|
||||
const hint = chatSection.querySelector('.hint');
|
||||
|
||||
Reference in New Issue
Block a user