|
@@ -165,19 +165,22 @@
|
|
>
|
|
>
|
|
<button
|
|
<button
|
|
class="audio-btn"
|
|
class="audio-btn"
|
|
- @click="
|
|
|
|
- isPlaying
|
|
|
|
- ? stopAudio()
|
|
|
|
- : playAudioMessage(message.audioData)
|
|
|
|
- "
|
|
|
|
|
|
+ @click="handleAudioClick(message)"
|
|
>
|
|
>
|
|
- <div v-if="isPlaying" class="wave-animation">
|
|
|
|
|
|
+ <!-- 只在当前消息正在播放时显示波形动画 -->
|
|
|
|
+ <div v-if="currentPlayingId === message.id" class="wave-animation">
|
|
<span class="wave-bar"></span>
|
|
<span class="wave-bar"></span>
|
|
<span class="wave-bar"></span>
|
|
<span class="wave-bar"></span>
|
|
<span class="wave-bar"></span>
|
|
<span class="wave-bar"></span>
|
|
<span class="wave-bar"></span>
|
|
<span class="wave-bar"></span>
|
|
</div>
|
|
</div>
|
|
- <img v-else :src="playIcon" alt="播放" class="audio-icon" />
|
|
|
|
|
|
+ <!-- 其他情况显示播放图标 -->
|
|
|
|
+ <img
|
|
|
|
+ v-else
|
|
|
|
+ :src="playIcon"
|
|
|
|
+ alt="播放"
|
|
|
|
+ class="audio-icon"
|
|
|
|
+ />
|
|
</button>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@@ -340,7 +343,7 @@
|
|
</template>
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
-import { ref, reactive, nextTick } from "vue";
|
|
|
|
|
|
+import { ref, reactive, nextTick, onUnmounted } from "vue";
|
|
import {
|
|
import {
|
|
PlusOutlined,
|
|
PlusOutlined,
|
|
FireOutlined,
|
|
FireOutlined,
|
|
@@ -403,6 +406,9 @@ const isTyping = ref(false);
|
|
const audioPlayer = ref(null);
|
|
const audioPlayer = ref(null);
|
|
const isPlaying = ref(false);
|
|
const isPlaying = ref(false);
|
|
|
|
|
|
|
|
+// 添加当前播放消息的 ID
|
|
|
|
+const currentPlayingId = ref(null);
|
|
|
|
+
|
|
// 方法
|
|
// 方法
|
|
const toggleAttachments = () => {
|
|
const toggleAttachments = () => {
|
|
showAttachments.value = !showAttachments.value;
|
|
showAttachments.value = !showAttachments.value;
|
|
@@ -705,46 +711,59 @@ const handleFileDrop = async (event) => {
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
-// 添加音频播放方法
|
|
|
|
-const playAudioMessage = (audioBase64) => {
|
|
|
|
|
|
+// 添加音频点击处理方法
|
|
|
|
+const handleAudioClick = (message) => {
|
|
|
|
+ if (currentPlayingId.value === message.id) {
|
|
|
|
+ stopAudio();
|
|
|
|
+ } else {
|
|
|
|
+ playAudioMessage(message.audioData, message.id);
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+// 修改音频播放方法
|
|
|
|
+const playAudioMessage = async (audioBase64, messageId) => {
|
|
try {
|
|
try {
|
|
- // 如果已经有音频在播放,先停止
|
|
|
|
- if (audioPlayer.value) {
|
|
|
|
- audioPlayer.value.pause();
|
|
|
|
- audioPlayer.value = null;
|
|
|
|
- }
|
|
|
|
|
|
+ // 停止当前播放的音频
|
|
|
|
+ stopAudio();
|
|
|
|
|
|
// 创建新的音频元素
|
|
// 创建新的音频元素
|
|
const audio = new Audio(audioBase64);
|
|
const audio = new Audio(audioBase64);
|
|
audioPlayer.value = audio;
|
|
audioPlayer.value = audio;
|
|
|
|
+ currentPlayingId.value = messageId;
|
|
|
|
|
|
// 添加事件监听
|
|
// 添加事件监听
|
|
- audio.addEventListener("ended", () => {
|
|
|
|
- isPlaying.value = false;
|
|
|
|
|
|
+ audio.addEventListener('ended', () => {
|
|
|
|
+ stopAudio();
|
|
});
|
|
});
|
|
|
|
|
|
- audio.addEventListener("error", (e) => {
|
|
|
|
- console.error("音频播放错误:", e);
|
|
|
|
- isPlaying.value = false;
|
|
|
|
|
|
+ audio.addEventListener('error', (e) => {
|
|
|
|
+ console.error('音频播放错误:', e);
|
|
|
|
+ stopAudio();
|
|
});
|
|
});
|
|
|
|
|
|
// 播放音频
|
|
// 播放音频
|
|
|
|
+ await audio.play();
|
|
isPlaying.value = true;
|
|
isPlaying.value = true;
|
|
- audio.play();
|
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
- console.error("音频播放失败:", error);
|
|
|
|
- isPlaying.value = false;
|
|
|
|
|
|
+ console.error('音频播放失败:', error);
|
|
|
|
+ stopAudio();
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
-// 添加停止播放方法
|
|
|
|
|
|
+// 修改停止播放方法
|
|
const stopAudio = () => {
|
|
const stopAudio = () => {
|
|
if (audioPlayer.value) {
|
|
if (audioPlayer.value) {
|
|
audioPlayer.value.pause();
|
|
audioPlayer.value.pause();
|
|
audioPlayer.value = null;
|
|
audioPlayer.value = null;
|
|
- isPlaying.value = false;
|
|
|
|
}
|
|
}
|
|
|
|
+ isPlaying.value = false;
|
|
|
|
+ currentPlayingId.value = null;
|
|
};
|
|
};
|
|
|
|
+
|
|
|
|
+// 在组件卸载时清理
|
|
|
|
+onUnmounted(() => {
|
|
|
|
+ stopAudio();
|
|
|
|
+});
|
|
</script>
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
<style scoped>
|
|
@@ -1433,7 +1452,7 @@ const stopAudio = () => {
|
|
}
|
|
}
|
|
|
|
|
|
.right_menu {
|
|
.right_menu {
|
|
- width: 300px;
|
|
|
|
|
|
+ width: 600px;
|
|
height: 100%;
|
|
height: 100%;
|
|
background: #f7f7f8;
|
|
background: #f7f7f8;
|
|
border-left: 1px solid rgba(0, 0, 0, 0.06);
|
|
border-left: 1px solid rgba(0, 0, 0, 0.06);
|
|
@@ -1618,20 +1637,20 @@ const stopAudio = () => {
|
|
/* 添加音频控制相关样式 */
|
|
/* 添加音频控制相关样式 */
|
|
.audio-controls {
|
|
.audio-controls {
|
|
margin-top: 8px;
|
|
margin-top: 8px;
|
|
- display: flex;
|
|
|
|
- align-items: center;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
.audio-btn {
|
|
.audio-btn {
|
|
background: transparent;
|
|
background: transparent;
|
|
border: none;
|
|
border: none;
|
|
- padding: 4px;
|
|
|
|
|
|
+ padding: 4px 8px;
|
|
cursor: pointer;
|
|
cursor: pointer;
|
|
display: flex;
|
|
display: flex;
|
|
align-items: center;
|
|
align-items: center;
|
|
justify-content: center;
|
|
justify-content: center;
|
|
- border-radius: 50%;
|
|
|
|
|
|
+ border-radius: 4px;
|
|
transition: background-color 0.2s;
|
|
transition: background-color 0.2s;
|
|
|
|
+ min-width: 32px;
|
|
|
|
+ height: 32px;
|
|
}
|
|
}
|
|
|
|
|
|
.audio-btn:hover {
|
|
.audio-btn:hover {
|