c5_labsci/fapp/ciyon_ap/components/ciy-audio/ciy-audio.vue
2026-01-27 00:52:00 +08:00

216 lines
6.3 KiB
Vue

<template>
<view class="_audio" v-if="!nonedisplay">
<view class="_main">
<view style="align-self: center;margin-right:0.5em;">
<view class="_icon" :class="btncls" @tap="play"></view>
</view>
<view class="flex1 rel">
<view style="text-align:left;font-weight:bold;margin-bottom:0.5em;letter-spacing: 2px;">{{title}}</view>
<view class="flex flex-center">
<view class="txt-smm">{{statxt}}</view>
<view class="flex1 _timepct">
<view class="itm" :style="{width:percent + '%'}"></view>
</view>
<view class="txt-smm">{{endtxt}}</view>
</view>
<view class="abs txt-right txt-smm" style="right:0;top:0;">
{{lang('audio.rate')}} <text class="kbd" @tap="setrate()">{{rates[rateidx].name}}</text>
</view>
</view>
</view>
</view>
</template>
<style scoped>
._main {
display: flex;
border-top: 1px solid var(--bg3);
border-bottom: 3px solid var(--bg5);
padding: 0.5em;
border-radius: 0.8em;
}
._timepct {
background: var(--bg6);
margin: 0 0.5em;
height: 3px;
}
._timepct>.itm {
background: var(--txt7);
height: 2px;
}
._audio {
color: var(--txt7);
border: 1px solid var(--bg7);
border-radius: 0.8em;
background: linear-gradient(0deg, var(--bg3), var(--bg5));
}
._icon {
width: 3em;
height: 3em;
}
._icon.play {
background-image: url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAyNCAxMDI0IiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTUxMiA4OTZjMjEyLjA3NDY2NyAwIDM4NC0xNzEuOTI1MzMzIDM4NC0zODRTNzI0LjA3NDY2NyAxMjggNTEyIDEyOCAxMjggMjk5LjkyNTMzMyAxMjggNTEyczE3MS45MjUzMzMgMzg0IDM4NCAzODR6IiBmaWxsPSIjMDAwMDAwIj48L3BhdGg+PHBhdGggZD0iTTg1LjMzMzMzMyA1MTJDODUuMzMzMzMzIDI3Ni4zNTIgMjc2LjM1MiA4NS4zMzMzMzMgNTEyIDg1LjMzMzMzM3M0MjYuNjY2NjY3IDE5MS4wMTg2NjcgNDI2LjY2NjY2NyA0MjYuNjY2NjY3LTE5MS4wMTg2NjcgNDI2LjY2NjY2Ny00MjYuNjY2NjY3IDQyNi42NjY2NjdTODUuMzMzMzMzIDc0Ny42NDggODUuMzMzMzMzIDUxMnpNNTEyIDE3MC42NjY2NjdDMzIzLjQ3NzMzMyAxNzAuNjY2NjY3IDE3MC42NjY2NjcgMzIzLjQ3NzMzMyAxNzAuNjY2NjY3IDUxMnMxNTIuODEwNjY3IDM0MS4zMzMzMzMgMzQxLjMzMzMzMyAzNDEuMzMzMzMzIDM0MS4zMzMzMzMtMTUyLjgxMDY2NyAzNDEuMzMzMzMzLTM0MS4zMzMzMzNTNzAwLjUyMjY2NyAxNzAuNjY2NjY3IDUxMiAxNzAuNjY2NjY3eiIgZmlsbD0iIzAwMDAwMCI+PC9wYXRoPjxwYXRoIGQ9Ik00MjYuNjY2NjY3IDUxMnYtMTQ5LjMzMzMzM2wxMTcuMzMzMzMzIDc0LjY2NjY2Nkw2NjEuMzMzMzMzIDUxMmwtMTE3LjMzMzMzMyA3NC42NjY2NjdMNDI2LjY2NjY2NyA2NjEuMzMzMzMzdi0xNDkuMzMzMzMzeiIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPjxwYXRoIGQ9Ik00MDYuMTQ0IDMyNS4yNjkzMzNhNDIuNjY2NjY3IDQyLjY2NjY2NyAwIDAgMSA0My40MzQ2NjcgMS40MDhsMjM0LjY2NjY2NiAxNDkuMzMzMzM0YTQyLjY2NjY2NyA0Mi42NjY2NjcgMCAwIDEgMCA3MS45Nzg2NjZsLTIzNC42NjY2NjYgMTQ5LjMzMzMzNEE0Mi42NjY2NjcgNDIuNjY2NjY3IDAgMCAxIDM4NCA2NjEuMzMzMzMzVjM2Mi42NjY2NjdhNDIuNjY2NjY3IDQyLjY2NjY2NyAwIDAgMSAyMi4xNDQtMzcuMzk3MzM0ek00NjkuMzMzMzMzIDQ0MC4zODR2MTQzLjIzMkw1ODEuODY2NjY3IDUxMiA0NjkuMzMzMzMzIDQ0MC4zODR6IiBmaWxsPSIjRkZGRkZGIj48L3BhdGg+PC9zdmc+");
}
._icon.pause {
background-image: url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAyNCAxMDI0IiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTUxNCAxMTQuM2MtMjE5LjkgMC0zOTguOSAxNzguOS0zOTguOSAzOTguOCAwLjEgMjIwIDE3OSAzOTguOSAzOTguOSAzOTguOSAyMTkuOSAwIDM5OC44LTE3OC45IDM5OC44LTM5OC45IDAtMjE5LjgtMTc4LjktMzk4LjgtMzk4LjgtMzk4Ljh6IG0tMzUuNiA1MzEuNWMwIDMyLjUtMjYuMyA1OC44LTU4LjggNTguOHMtNTguOC0yNi4zLTU4LjgtNTguOFYzODEuNGMwLTMyLjUgMjYuMy01OC44IDU4LjgtNTguOHM1OC44IDI2LjMgNTguOCA1OC44djI2NC40eiBtMTg4LjcgMGMwIDMyLjUtMjYuMyA1OC44LTU4LjggNTguOHMtNTguOC0yNi4zLTU4LjgtNTguOFYzODEuNGMwLTMyLjUgMjYuMy01OC44IDU4LjgtNTguOHM1OC44IDI2LjMgNTguOCA1OC44djI2NC40eiIgZmlsbD0iIzBDMEMwQyI+PC9wYXRoPjwvc3ZnPg==");
}
</style>
<script>
export default {
emits: ['change'],
props: {
src: {
type: String,
default: ''
},
title: {
type: String,
default: '无题'
},
background: {
type: Boolean,
default: false
},
nonedisplay: {
type: Boolean,
default: false
},
coverimg: {
type: String,
default: ''
},
epname: { //专辑名
type: String,
default: ''
},
singer: { //歌手名
type: String,
default: ''
},
},
data() {
return {
btncls: 'play',
percent: 0,
rateidx: 1,
rates: [{
rate: 0.5,
name: 'x0.5'
}, {
rate: 1,
name: 'x1'
}, {
rate: 1.25,
name: 'x1.25'
}, {
rate: 1.5,
name: 'x1.5'
}, {
rate: 2,
name: 'x2'
}],
statxt: '00:00',
endtxt: '00:00'
};
},
watch: {
src(newD, oldD) {
this.sesrc(newD);
},
title(newD, oldD) {
this.aud.title = newD;
},
coverimg(newD, oldD) {
this.aud.coverImgUrl = newD;
},
epname(newD, oldD) {
this.aud.epname = newD;
},
singer(newD, oldD) {
this.aud.singer = newD;
}
},
mounted() {
if (!this.aud) {
if (this.background)
this.aud = wx.getBackgroundAudioManager();
else
this.aud = uni.createInnerAudioContext();
}
this.aud.title = this.title;
if (this.background) {
this.aud.epname = this.epname;
this.aud.singer = this.singer;
this.aud.coverImgUrl = this.coverimg;
}
this.setsrc(this.src);
this.aud.onPlay(e => {
this.btncls = 'pause';
this.$emit('change', {
from: 'play',
value: this.aud
});
});
this.aud.onEnded(e => {
this.percent = 100;
this.statxt = this.endtxt;
this.btncls = 'play';
this.$emit('change', {
from: 'stop',
value: this.aud
});
});
this.aud.onPause(e => {
this.btncls = 'play';
this.$emit('change', {
from: 'pause',
value: this.aud
});
});
this.aud.onTimeUpdate(e => {
this.endtxt = this.sttime(this.aud.duration);
this.statxt = this.sttime(this.aud.currentTime);
this.percent = this.aud.currentTime / this.aud.duration * 100;
this.btncls = 'pause';
});
},
unmounted() {
this.aud.stop();
this.aud.destroy();
},
methods: {
setsrc(src) {
if (!this.aud)
return;
this.aud.src = src;
//this.aud.protocol = 'hls';
},
setrate() {
this.rateidx++;
if (this.rateidx >= this.rates.length)
this.rateidx = 0;
this.aud.playbackRate = this.rates[this.rateidx].rate;
},
sttime(s) {
var m = parseInt(s / 60);
var ss = parseInt(s - m * 60);
if (ss < 10)
ss = '0' + ss;
return m + ':' + ss;
},
play() {
if (this.btncls == 'play')
this.aud.play();
else
this.aud.pause();
}
}
}
</script>