|
@@ -1,38 +1,66 @@
|
|
|
<template>
|
|
|
- <div :class="['sound-record-wrapper', 'sound-record-wrapper-' + type]" :style="{ justifyContent: position }">
|
|
|
- <div class="sound-item sound-item-luyin">
|
|
|
- <img
|
|
|
- v-if="microphoneStatus"
|
|
|
- :src="require('../../../../../assets/record-ing-hasBg.png')"
|
|
|
- class="voice-play"
|
|
|
- @click="microphone"
|
|
|
+ <div class="sound-record-preview">
|
|
|
+ <div v-if="type === 'big' && file_url" class="audio-slider-box audio-slider-box-big">
|
|
|
+ <span class="audio-time">{{ secondFormatConversion(audio.current_time) }}</span>
|
|
|
+ <el-slider
|
|
|
+ v-model="play_value"
|
|
|
+ class="audio-slider"
|
|
|
+ :format-tooltip="formatProcessToolTip"
|
|
|
+ @change="changeCurrentTime"
|
|
|
/>
|
|
|
- <span v-else class="sound-item-span" @click="microphone">
|
|
|
- <SvgIcon icon-class="mic-line" :size="iconSize" class="record" />
|
|
|
- </span>
|
|
|
-
|
|
|
- <label v-if="type === 'big'" :class="['record-time', microphoneStatus ? 'record-ing' : '']">
|
|
|
- {{ audio.paused ? '' : '-' }}{{ secondFormatConversion(recordTimes) }}
|
|
|
- </label>
|
|
|
+ <span class="audio-time">{{ audio_allTime }}</span>
|
|
|
</div>
|
|
|
- <div v-if="type === 'small'" class="sound-item">
|
|
|
- <label :class="['record-time', microphoneStatus ? 'record-ing' : '']">
|
|
|
+ <div :class="['sound-record-wrapper', 'sound-record-wrapper-' + type]" :style="{ justifyContent: position }">
|
|
|
+ <div class="sound-item sound-item-luyin">
|
|
|
+ <img
|
|
|
+ v-if="microphoneStatus"
|
|
|
+ :src="require('../../../../../assets/record-ing-hasBg.png')"
|
|
|
+ class="voice-play"
|
|
|
+ @click="microphone"
|
|
|
+ />
|
|
|
+ <span v-else class="sound-item-span" @click="microphone">
|
|
|
+ <SvgIcon icon-class="mic-line" :size="iconSize" class="record" />
|
|
|
+ </span>
|
|
|
+
|
|
|
+ <label v-if="type === 'big'" :class="['record-time', microphoneStatus ? 'record-ing' : '']">
|
|
|
+ {{ microphoneStatus ? secondFormatConversion(recordTimes) : '录音' }}
|
|
|
+ </label>
|
|
|
+ </div>
|
|
|
+ <div v-if="type === 'small' && file_url" class="sound-item audio-slider-box">
|
|
|
+ <span class="audio-time">{{ secondFormatConversion(audio.current_time) }}</span>
|
|
|
+ <el-slider
|
|
|
+ v-model="play_value"
|
|
|
+ class="audio-slider"
|
|
|
+ :format-tooltip="formatProcessToolTip"
|
|
|
+ @change="changeCurrentTime"
|
|
|
+ />
|
|
|
+ <span class="audio-time">{{ audio_allTime }}</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <label v-if="type === 'small' && !file_url" :class="['record-time', microphoneStatus ? 'record-ing' : '']">
|
|
|
{{ audio.paused ? '' : '-' }}{{ secondFormatConversion(recordTimes) }}
|
|
|
</label>
|
|
|
+ <div class="sound-item">
|
|
|
+ <span :class="['sound-item-span sound-item-btn', wavBlob ? '' : 'not-url']" @click="playMicrophone">
|
|
|
+ <SvgIcon :icon-class="iconClass" :size="iconSize" :class="['audio-play-btn']" />
|
|
|
+ </span>
|
|
|
+ <label v-if="type === 'big'" class="tips">回放</label>
|
|
|
+ </div>
|
|
|
+ <div class="sound-item">
|
|
|
+ <span :class="['sound-item-span sound-item-btn', wavBlob ? '' : 'not-url']" @click="delectWav">
|
|
|
+ <SvgIcon icon-class="delete-back-line" :size="iconSize" :class="['delete-btn']" />
|
|
|
+ </span>
|
|
|
+ <label v-if="type === 'big'" class="tips">删除</label>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <div class="sound-item">
|
|
|
- <span :class="['sound-item-span sound-item-btn', wavBlob ? '' : 'not-url']" @click="playMicrophone">
|
|
|
- <SvgIcon :icon-class="iconClass" :size="iconSize" :class="['audio-play-btn']" />
|
|
|
- </span>
|
|
|
- <label v-if="type === 'big'" class="tips">回放</label>
|
|
|
- </div>
|
|
|
- <div class="sound-item">
|
|
|
- <span :class="['sound-item-span sound-item-btn', wavBlob ? '' : 'not-url']" @click="delectWav">
|
|
|
- <SvgIcon icon-class="delete-back-line" :size="iconSize" :class="['delete-btn']" />
|
|
|
- </span>
|
|
|
- <label v-if="type === 'big'" class="tips">删除</label>
|
|
|
- </div>
|
|
|
- <audio ref="audio" :src="file_url" preload="metadata"></audio>
|
|
|
+ <audio
|
|
|
+ :ref="wavBlob"
|
|
|
+ :src="file_url"
|
|
|
+ preload="metadata"
|
|
|
+ @loadedmetadata="onLoadedmetadata"
|
|
|
+ @timeupdate="onTimeupdate"
|
|
|
+ @canplaythrough="oncanplaythrough"
|
|
|
+ ></audio>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
@@ -74,13 +102,22 @@ export default {
|
|
|
timer: null, // 计时器
|
|
|
microphoneStatus: false, // 是否录音
|
|
|
hasMicro: '', // 录音后的样式class
|
|
|
- audio: {
|
|
|
- paused: true,
|
|
|
- },
|
|
|
playtime: 0, // 播放时间
|
|
|
recordTimes: 0,
|
|
|
file_url: '',
|
|
|
recordTime: 0,
|
|
|
+ audio: {
|
|
|
+ paused: true,
|
|
|
+ playing: false,
|
|
|
+ // 音频当前播放时长
|
|
|
+ current_time: 0,
|
|
|
+ // 音频最大播放时长
|
|
|
+ max_time: 0,
|
|
|
+ isPlaying: false,
|
|
|
+ loading: false,
|
|
|
+ },
|
|
|
+ play_value: 0,
|
|
|
+ audio_allTime: null, // 展示总时间
|
|
|
};
|
|
|
},
|
|
|
computed: {
|
|
@@ -110,13 +147,13 @@ export default {
|
|
|
},
|
|
|
},
|
|
|
mounted() {
|
|
|
- this.$refs.audio.addEventListener('ended', () => {
|
|
|
+ this.$refs[this.wavBlob].addEventListener('ended', () => {
|
|
|
this.audio.paused = true;
|
|
|
});
|
|
|
- this.$refs.audio.addEventListener('pause', () => {
|
|
|
+ this.$refs[this.wavBlob].addEventListener('pause', () => {
|
|
|
this.audio.paused = true;
|
|
|
});
|
|
|
- this.$refs.audio.addEventListener('play', () => {
|
|
|
+ this.$refs[this.wavBlob].addEventListener('play', () => {
|
|
|
this.audio.paused = false;
|
|
|
});
|
|
|
},
|
|
@@ -128,7 +165,7 @@ export default {
|
|
|
this.hasMicro = 'active';
|
|
|
// this.$refs.audio.pause();
|
|
|
// this.$refs.audio.load();
|
|
|
- this.$refs.audio.play();
|
|
|
+ this.$refs[this.wavBlob].play();
|
|
|
if (this.recordTimes === 0) {
|
|
|
this.recordTimes = JSON.parse(JSON.stringify(this.recordTime));
|
|
|
this.playtime = 0;
|
|
@@ -145,7 +182,7 @@ export default {
|
|
|
}
|
|
|
}, 1000);
|
|
|
} else {
|
|
|
- this.$refs.audio.pause();
|
|
|
+ this.$refs[this.wavBlob].pause();
|
|
|
this.hasMicro = 'normal';
|
|
|
clearInterval(this.timer);
|
|
|
}
|
|
@@ -154,7 +191,7 @@ export default {
|
|
|
// 开始录音
|
|
|
microphone() {
|
|
|
if (!this.audio.paused) {
|
|
|
- this.$refs.audio.pause();
|
|
|
+ this.$refs[this.wavBlob].pause();
|
|
|
this.audio.paused = true;
|
|
|
}
|
|
|
if (this.disabled) return;
|
|
@@ -194,7 +231,7 @@ export default {
|
|
|
},
|
|
|
// 删除录音
|
|
|
delectWav() {
|
|
|
- this.$refs.audio.pause();
|
|
|
+ this.$refs[this.wavBlob].pause();
|
|
|
this.hasMicro = '';
|
|
|
this.microphoneStatus = false;
|
|
|
this.playtime = 0;
|
|
@@ -202,6 +239,50 @@ export default {
|
|
|
clearInterval(this.timer);
|
|
|
this.$emit('update:wavBlob', '');
|
|
|
},
|
|
|
+ // 进度条格式化toolTip
|
|
|
+ formatProcessToolTip(index) {
|
|
|
+ let indexs = parseInt((this.audio.max_time / 100) * index);
|
|
|
+ return secondFormatConversion(indexs);
|
|
|
+ },
|
|
|
+ // 点击 拖拽播放音频
|
|
|
+ changeCurrentTime(value) {
|
|
|
+ let audioId = this.wavBlob;
|
|
|
+ this.$refs[audioId].play();
|
|
|
+ this.audio.playing = true;
|
|
|
+ this.$refs[audioId].currentTime = parseInt((value / 100) * this.audio.max_time);
|
|
|
+ },
|
|
|
+ // 音频加载完之后
|
|
|
+ onLoadedmetadata(res) {
|
|
|
+ this.audio.max_time = parseInt(res.target.duration);
|
|
|
+ this.audio_allTime = secondFormatConversion(this.audio.max_time);
|
|
|
+ },
|
|
|
+ // 当音频当前时间改变后,进度条也要改变
|
|
|
+ onTimeupdate(res) {
|
|
|
+ let audioId = this.wavBlob;
|
|
|
+ this.audio.current_time = res.target.currentTime;
|
|
|
+ this.play_value = (this.audio.current_time / this.audio.max_time) * 100;
|
|
|
+ if (this.audio.current_time * 1000 > this.ed) {
|
|
|
+ this.$refs[audioId].pause();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onTimeupdateTime(res, playFlag) {
|
|
|
+ if (!res && res !== 0) return;
|
|
|
+ let audioId = this.wavBlob;
|
|
|
+ this.$refs[audioId].currentTime = res;
|
|
|
+ this.play_value = (res / this.audio.max_time) * 100;
|
|
|
+ if (playFlag) {
|
|
|
+ let audio = document.getElementsByTagName('audio');
|
|
|
+ audio.forEach((item) => {
|
|
|
+ if (item.id !== audioId) {
|
|
|
+ item.pause();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ this.$refs[audioId].play();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ oncanplaythrough() {
|
|
|
+ this.audio.loading = false;
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
</script>
|
|
@@ -259,9 +340,8 @@ export default {
|
|
|
display: block;
|
|
|
margin-top: 4px;
|
|
|
font-size: 12px;
|
|
|
- font-weight: 500;
|
|
|
line-height: 20px;
|
|
|
- color: #000;
|
|
|
+ color: rgba(0, 0, 0, 50%);
|
|
|
}
|
|
|
|
|
|
&-small {
|
|
@@ -287,4 +367,57 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+.audio-slider-box {
|
|
|
+ display: flex;
|
|
|
+ column-gap: 8px;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ .audio-time {
|
|
|
+ min-width: 35px;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: 400;
|
|
|
+ line-height: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .audio-slider {
|
|
|
+ width: 82px;
|
|
|
+ height: 32px;
|
|
|
+
|
|
|
+ :deep .el-slider__runway {
|
|
|
+ height: 4px;
|
|
|
+ margin: 14px 0;
|
|
|
+ background-color: #dadada;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep .el-slider__button {
|
|
|
+ width: 4px;
|
|
|
+ height: 4px;
|
|
|
+ background-color: #000;
|
|
|
+ border: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep .el-slider__bar {
|
|
|
+ height: 4px;
|
|
|
+ background-color: #000;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep .el-slider__button-wrapper {
|
|
|
+ top: -16px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &-big {
|
|
|
+ width: 280px;
|
|
|
+ height: 40px;
|
|
|
+ padding: 4px 12px;
|
|
|
+ margin: 16px auto;
|
|
|
+ background-color: #ededed;
|
|
|
+ border-radius: 28px;
|
|
|
+
|
|
|
+ .audio-slider {
|
|
|
+ width: 178px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|