208 lines
4.4 KiB
Vue
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>
|