Files
lilishop-ui/im/src/components/chat/messaege/AudioMessage.vue
lifenlong 88fc1b0b2a refactor: 四端完成 Options API → script setup + vuex → pinia 迁移
- buyer(95) / seller(169) / im(53) / manager(280) 共 597 个组件全部从 Options API 转换为 <script setup>
- 四端 vuex 全部移除,状态管理统一迁移至 pinia 4(stores/ 目录)
- util.js 等基础设施去除 vm 首参依赖;全局属性($Message/$filters 等)在 script 内改为具名导入
- 被外部 ref 访问的公共组件均已补齐 defineExpose(清单见各端 MIGRATION-VUE3.md)
- 各端 eslint 启用 vue/component-api-style 防止新代码回退 Options API
- 四端 yarn build 全部通过;迁移约定与注意事项已更新至各端 MIGRATION-VUE3.md
2026-10-13 07:06:59 +08:00

188 lines
3.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="audio-message">
<div class="videodisc">
<div class="disc" :class="{ play: isPlay }" @click="toPlay">
<legacy-el-icon v-if="loading" name="el-icon-loading" />
<legacy-el-icon v-else-if="isPlay" name="el-icon-video-pause" />
<legacy-el-icon v-else name="el-icon-video-play" />
<audio
ref="audio"
type="audio/mp3"
:src="src"
@timeupdate="timeupdate"
@ended="ended"
@canplay="canplay"
></audio>
</div>
</div>
<div class="detail">
<div class="text">
<legacy-el-icon name="el-icon-service" />
<span>{{ getCurrDuration }} / {{ getTotalDuration }}</span>
</div>
<div class="process">
<el-progress :percentage="progress" :show-text="false" />
</div>
</div>
</div>
</template>
<script setup>
import { computed, ref } from "vue";
defineOptions({ name: 'AudioMessage' });
defineProps({
src: {
type: String,
default: '',
},
});
function formatSeconds(value) {
var theTime = parseInt(value) // 秒
var theTime1 = 0 // 分
var theTime2 = 0 // 小时
if (theTime > 60) {
theTime1 = parseInt(theTime / 60)
theTime = parseInt(theTime % 60)
if (theTime1 > 60) {
theTime2 = parseInt(theTime1 / 60)
theTime1 = parseInt(theTime1 % 60)
}
}
var result = '' + parseInt(theTime) //秒
if (10 > theTime > 0) {
result = '0' + parseInt(theTime) //秒
} else {
result = '' + parseInt(theTime) //秒
}
if (10 > theTime1 > 0) {
result = '0' + parseInt(theTime1) + ':' + result //分,不足两位数,首位补充0,
} else {
result = '' + parseInt(theTime1) + ':' + result //分
}
if (theTime2 > 0) {
result = '' + parseInt(theTime2) + ':' + result //时
}
return result
}
const loading = ref(true)
const isPlay = ref(false)
const duration = ref(0)
const currentTime = ref(0)
const progress = ref(0)
const audio = ref(null)
const getTotalDuration = computed(() => formatSeconds(duration.value))
const getCurrDuration = computed(() => formatSeconds(currentTime.value))
function toPlay() {
if (loading.value) {
return
}
let audioEl = audio.value
if (isPlay.value) {
audioEl.pause()
} else {
audioEl.play()
}
isPlay.value = !isPlay.value
}
// 当目前的播放位置已更改时
function timeupdate() {
let audioEl = audio.value
currentTime.value = audioEl.currentTime
progress.value = (audioEl.currentTime / audioEl.duration) * 100
}
// 当浏览器可以播放音频/视频时
function canplay() {
duration.value = audio.value.duration
loading.value = false
}
// 当目前的播放列表已结束时
function ended() {
isPlay.value = false
}
</script>
<style scoped lang="less">
.audio-message {
width: 200px;
height: 60px;
border-radius: 5px;
background: #ffffff;
display: flex;
align-items: center;
border: 1px solid #03a9f4;
overflow: hidden;
> div {
height: 100%;
}
.videodisc {
flex-basis: 60px;
flex-shrink: 0;
display: flex;
justify-content: center;
align-items: center;
.disc {
width: 42px;
height: 42px;
background: #e9e5e5;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
cursor: pointer;
transition: ease 0.5;
&.play {
background: #ff5722;
box-shadow: 0 0 4px 0px #f76a3e;
}
i {
font-size: 24px;
}
&:active i {
transform: scale(1.1);
}
}
}
.detail {
flex: 1 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding-top: 10px;
.text {
width: 90%;
font-size: 12px;
i {
margin-right: 5px;
}
}
.process {
padding-top: 10px;
height: 20px;
width: 90%;
}
}
}
</style>