Files
tk-mini-program-PC/src/components/chatMessage/voiceMessage.vue
pengxiaolong 2a5ae6c0cc 优化代码
2025-08-26 13:31:21 +08:00

208 lines
4.4 KiB
Vue

<template>
<!-- <div class="audio-player">
<button @click="togglePlay" :class="{ playing: isPlaying }">
{{ isPlaying ? "暂停" : "播放" }}
</button>
</div> -->
<div class="voice-message">
<!-- 对方消息 -->
<div class="voice-message" v-if="user.id != senderId" @click="togglePlay">
<img
v-if="!isPlaying"
class="voice-icon"
src="https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/voice.png"
alt=""
/>
<div class="voice-icon-text" v-if="!isPlaying">'{{floor(size)}}'</div>
<div class="voice-message-text" v-if="isPlaying">
播放中...
</div>
</div>
<!-- 自己消息 -->
<div class="voice-message" v-if="user.id == senderId" @click="togglePlay">
<div class="voice-icon-text" v-if="!isPlaying">'{{floor(size)}}'</div>
<img
v-if="!isPlaying"
class="voice-icon"
src="https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/voice.png"
alt=""
/>
<div class="voice-message-text" v-if="isPlaying">
播放中...
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, watch } from "vue";
import { setStorage, getStorage, getPromiseStorage } from "@/utils/storage.js";
const props = defineProps({
item: {
type: String,
required: true,
},
size:{
type: String,
required: true,
},
senderId: {
type: String,
required: true,
},
});
const audioElement = ref(null);
const isPlaying = ref(false);
const currentTime = ref(0);
const duration = ref(0);
const currentProgress = ref(0);
const volume = ref(0.5);
const user = ref({});
function floor(num) {
return Math.floor(num);
}
// 格式化时间
const formatTime = (time) => {
const minutes = Math.floor(time / 60);
const seconds = Math.floor(time % 60);
return `${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
};
// 切换播放状态
const togglePlay = () => {
isPlaying.value = !isPlaying.value;
isPlaying.value ? audioElement.value.play() : audioElement.value.pause();
};
// 更新进度条
const updateProgress = () => {
currentTime.value = audioElement.value.currentTime;
currentProgress.value = (currentTime.value / duration.value) * 100;
};
// 跳转到指定时间
const seekTo = (e) => {
const newTime = (e.target.value / 100) * duration.value;
audioElement.value.currentTime = newTime;
};
// 更新音量
const updateVolume = () => {
audioElement.value.volume = volume.value;
};
// 监听音频加载完成
watch(
() => props.item,
(newSrc) => {
if (audioElement.value) {
audioElement.value.src = newSrc;
audioElement.value.load();
}
}
);
onMounted(() => {
getPromiseStorage("user")
.then((res) => {
user.value = res;
})
.catch((err) => {
console.log(err);
});
audioElement.value = new Audio(props.item);
audioElement.value.volume = volume.value;
// 监听音频事件
audioElement.value.addEventListener("timeupdate", updateProgress);
audioElement.value.addEventListener("loadedmetadata", () => {
duration.value = audioElement.value.duration;
});
audioElement.value.addEventListener("ended", () => {
isPlaying.value = false;
currentTime.value = 0;
currentProgress.value = 0;
});
// 自动播放策略处理
if ("autoPlayEnabled" in audioElement.value) {
audioElement.value.autoPlayEnabled = false;
}
});
</script>
<style scoped>
.voice-message {
width: 120px;
height: 50px;
display: flex;
align-items: center;
justify-content:space-around;
}
.voice-message-text{
width: 120px;
height: 50px;
line-height: 50px;
text-align: center;
font-size: 14px;
color: #999;
}
.voice-icon {
width: 70px;
height: 50px;
}
.voice-icon-text {
font-size: 14px;
color: #999;
}
.audio-player {
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
padding: 2rem;
background: #f5f5f5;
border-radius: 8px;
}
button {
padding: 0.5rem 1rem;
font-size: 1.2rem;
cursor: pointer;
transition: background-color 0.3s;
}
button.playing {
background-color: #4caf50;
color: white;
}
.progress-container {
display: flex;
align-items: center;
gap: 1rem;
}
.progress-bar {
width: 300px;
-webkit-appearance: none;
height: 5px;
background: #ddd;
}
.volume-control {
display: flex;
align-items: center;
gap: 0.5rem;
}
input[type="range"] {
-webkit-appearance: none;
width: 150px;
}
</style>