mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-11-07 01:18:54 +08:00
- 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
188 lines
3.9 KiB
Vue
188 lines
3.9 KiB
Vue
<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>
|