|
|
@@ -0,0 +1,552 @@
|
|
|
+<template>
|
|
|
+ <div class="AudioNNPE">
|
|
|
+ <div class="audioLine" v-if="mp3List">
|
|
|
+ <span class="audioName">{{activeIndex+1}}.</span>
|
|
|
+ <div class="go-start" :class="[activeIndex===0?'disabled':'']" @click="handleActiveIndex('-')"></div>
|
|
|
+ <div class="playBox" @click="PlayAudio">
|
|
|
+ <div
|
|
|
+ class="play"
|
|
|
+ :class="[
|
|
|
+ audio.loading ? 'loadBtn' : audio.playing ? 'playBtn' : 'pauseBtn',
|
|
|
+ ]"
|
|
|
+ ></div>
|
|
|
+ </div>
|
|
|
+ <div class="go-end" :class="[activeIndex!=mp3List.length-1?'':'disabled']" @click="handleActiveIndex('+')"></div>
|
|
|
+ <div class="play-mode order" :class="[isRepeatAudio?'roll':'']" @click="handleRepeatAudio"></div>
|
|
|
+ <template>
|
|
|
+ <el-slider
|
|
|
+ v-model="playValue"
|
|
|
+ :style="{ width: sliderWidth + 'px', height: '2px' }"
|
|
|
+ :format-tooltip="formatProcessToolTip"
|
|
|
+ @change="changeCurrentTime"
|
|
|
+ />
|
|
|
+ <span class="time-box"
|
|
|
+ ><template v-if="audio.playing">-</template
|
|
|
+ >{{
|
|
|
+ audio.maxTime
|
|
|
+ ? realFormatSecond(audio.maxTime - audio.currentTime)
|
|
|
+ : ""
|
|
|
+ }}</span
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ <div class="common-btn audio-btn" :class="[mp3ListShow?'active':'']" @click="handleClickAudio">
|
|
|
+ <img src="../../../assets/common/music-list.png" class="music-list" />
|
|
|
+ <ul class="audioList" v-if="mp3ListShow">
|
|
|
+ <li v-for="(item,index) in mp3List" :key="index" :class="[activeIndex==index?'active':'']" @click="handleSelectAudio(index)">
|
|
|
+ <span>{{index+1}}.</span>
|
|
|
+ <p>{{realFormatSecond(item.media_duration)}}</p>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+ <div class="common-btn download-btn" @click="download">
|
|
|
+ <img src="../../../assets/common/download.png" class="download" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <audio
|
|
|
+ :ref="audioId"
|
|
|
+ :src="mp3List[activeIndex].file_url"
|
|
|
+ @loadedmetadata="onLoadedmetadata"
|
|
|
+ @timeupdate="onTimeupdate"
|
|
|
+ @canplaythrough="oncanplaythrough"
|
|
|
+ preload="meta"
|
|
|
+ :id="audioId"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+// 这里可以导入其它文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
|
|
|
+// 例如:import 《组件名称》from ‘《组件路径》';
|
|
|
+import { getToken } from "@/utils/auth";
|
|
|
+export default {
|
|
|
+ // import引入的组件需要注入到对象中才能使用
|
|
|
+ components: {},
|
|
|
+ props: [
|
|
|
+ "mp3List",
|
|
|
+ "audioId",
|
|
|
+ "type",
|
|
|
+ ],
|
|
|
+ data() {
|
|
|
+ // 这里存放数据
|
|
|
+ return {
|
|
|
+ playValue: 0,
|
|
|
+ audio: {
|
|
|
+ // 该字段是音频是否处于播放状态的属性
|
|
|
+ playing: false,
|
|
|
+ // 音频当前播放时长
|
|
|
+ currentTime: 0,
|
|
|
+ // 音频最大播放时长
|
|
|
+ maxTime: 0,
|
|
|
+ isPlaying: false,
|
|
|
+ loading: false,
|
|
|
+ },
|
|
|
+ audioAllTime: null, // 展示总时间
|
|
|
+ duioCurrentTime: null, // 剩余时间
|
|
|
+ count: 0,
|
|
|
+ isClick: false,
|
|
|
+ activeIndex:0,
|
|
|
+ mp3ListShow: false,
|
|
|
+ isRepeatAudio:false,
|
|
|
+ };
|
|
|
+ },
|
|
|
+ // 计算属性 类似于data概念
|
|
|
+ computed: {
|
|
|
+ sliderWidth() {
|
|
|
+ let width = 0;
|
|
|
+ if (this.width) {
|
|
|
+ width = this.width;
|
|
|
+ } else {
|
|
|
+ width = 696;
|
|
|
+ }
|
|
|
+ return width;
|
|
|
+ },
|
|
|
+ },
|
|
|
+ // 监控data中数据变化
|
|
|
+ watch: {
|
|
|
+ stopAudio: {
|
|
|
+ handler(val, oldVal) {
|
|
|
+ const _this = this;
|
|
|
+ if (val) {
|
|
|
+ _this.$refs[_this.audioId].pause();
|
|
|
+ _this.audio.playing = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 深度观察监听
|
|
|
+ deep: true,
|
|
|
+ },
|
|
|
+ "audio.playing": {
|
|
|
+ handler(val) {
|
|
|
+ this.$emit("playChange", val);
|
|
|
+ if (val) this.$emit("handleChangeStopAudio");
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ // 生命周期 - 创建完成(可以访问当前this实例)
|
|
|
+ created() {},
|
|
|
+ // 生命周期 - 挂载完成(可以访问DOM元素)
|
|
|
+ mounted() {
|
|
|
+ let _this = this;
|
|
|
+ let audioId = _this.audioId;
|
|
|
+ _this.$refs[audioId].addEventListener("loadstart", function () {
|
|
|
+ console.log("音频开始加载");
|
|
|
+ });
|
|
|
+ _this.$refs[audioId].addEventListener("play", function () {
|
|
|
+ console.log("音频开始播放了");
|
|
|
+ _this.audio.playing = true;
|
|
|
+ _this.audio.isPlaying = true;
|
|
|
+ _this.audio.loading = false;
|
|
|
+ });
|
|
|
+ _this.$refs[audioId].addEventListener("pause", function () {
|
|
|
+ _this.audio.playing = false;
|
|
|
+ if (_this.hideSlider && _this.audio.currentTime * 1000 + 500 > _this.ed) {
|
|
|
+ _this.$emit("sentPause", true);
|
|
|
+ }
|
|
|
+ _this.$emit("handleListenRead", false);
|
|
|
+ });
|
|
|
+ _this.$refs[audioId].addEventListener("ended", function () {
|
|
|
+ _this.audio.playing = false;
|
|
|
+ _this.audio.isPlaying = false;
|
|
|
+ _this.isClick = false;
|
|
|
+ _this.$emit("handleListenRead", false);
|
|
|
+ if(_this.isRepeatAudio){
|
|
|
+ _this.PlayAudio()
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (
|
|
|
+ document.getElementsByClassName("el-slider__button-wrapper") &&
|
|
|
+ document.getElementsByClassName("el-slider__button-wrapper")[0]
|
|
|
+ ) {
|
|
|
+ document
|
|
|
+ .getElementsByClassName("el-slider__button-wrapper")[0]
|
|
|
+ .addEventListener("mousedown", function () {
|
|
|
+ _this.$refs[audioId].pause();
|
|
|
+ _this.audio.playing = false;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 生命周期-挂载之前
|
|
|
+ beforeMount() {},
|
|
|
+ // 生命周期-更新之后
|
|
|
+ updated() {},
|
|
|
+ // 如果页面有keep-alive缓存功能,这个函数会触发
|
|
|
+ activated() {},
|
|
|
+ // 方法集合
|
|
|
+ methods: {
|
|
|
+ PlayAudio() {
|
|
|
+ let audioId = this.audioId;
|
|
|
+ let audio = document.getElementsByTagName("audio");
|
|
|
+ audio.forEach((item) => {
|
|
|
+ if (item.src == this.mp3List[this.activeIndex]) {
|
|
|
+ if (item.id !== audioId) {
|
|
|
+ item.pause();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ item.pause();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (this.audio.playing) {
|
|
|
+ this.$refs[audioId].pause();
|
|
|
+ this.audio.playing = false;
|
|
|
+ this.$emit("handleListenRead", false);
|
|
|
+ this.isClick = false;
|
|
|
+ } else {
|
|
|
+ if (this.count == 0) {
|
|
|
+ this.audio.loading = true;
|
|
|
+ this.count++;
|
|
|
+ }
|
|
|
+ if (this.hideSlider) {
|
|
|
+ this.$refs[audioId].play();
|
|
|
+ this.onTimeupdateTime(this.bg / 1000);
|
|
|
+ } else {
|
|
|
+ this.$refs[audioId].play();
|
|
|
+ }
|
|
|
+
|
|
|
+ this.$emit("handleChangeStopAudio");
|
|
|
+ this.$emit("handleListenRead", true);
|
|
|
+ this.isClick = true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ oncanplaythrough() {
|
|
|
+ let _this = this;
|
|
|
+ //setTimeout(() => {
|
|
|
+ console.log("音频加载完成");
|
|
|
+ _this.audio.loading = false;
|
|
|
+ //}, 10000);
|
|
|
+ },
|
|
|
+ // 点击 拖拽播放音频
|
|
|
+ changeCurrentTime(value) {
|
|
|
+ let audioId = this.audioId;
|
|
|
+ this.$refs[audioId].play();
|
|
|
+ this.audio.playing = true;
|
|
|
+ this.$refs[audioId].currentTime = parseInt(
|
|
|
+ (value / 100) * this.audio.maxTime
|
|
|
+ );
|
|
|
+ },
|
|
|
+ mousedown() {
|
|
|
+ let audioId = this.audioId;
|
|
|
+ this.$refs[audioId].pause();
|
|
|
+ this.audio.playing = false;
|
|
|
+ },
|
|
|
+ // 进度条格式化toolTip
|
|
|
+ formatProcessToolTip(index) {
|
|
|
+ index = parseInt((this.audio.maxTime / 100) * index);
|
|
|
+ return this.realFormatSecond(index);
|
|
|
+ },
|
|
|
+ // 音频加载完之后
|
|
|
+ onLoadedmetadata(res) {
|
|
|
+ // this.audio.maxTime = parseInt(res.target.duration);
|
|
|
+ this.audio.maxTime = this.mp3List[this.activeIndex].media_duration
|
|
|
+ this.audioAllTime = this.realFormatSecond(this.audio.maxTime);
|
|
|
+ },
|
|
|
+ // 当音频当前时间改变后,进度条也要改变
|
|
|
+ onTimeupdate(res) {
|
|
|
+ let audioId = this.audioId;
|
|
|
+ this.audio.currentTime = res.target.currentTime;
|
|
|
+ this.playValue = (this.audio.currentTime / this.audio.maxTime) * 100;
|
|
|
+ if (this.type == "audioLine") {
|
|
|
+ if (!this.isClick && this.audio.currentTime * 1000 > this.ed) {
|
|
|
+ this.$refs[audioId].pause();
|
|
|
+ this.$emit("emptyEd");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (this.hideSlider) {
|
|
|
+ if (this.audio.currentTime * 1000 + 500 > this.ed) {
|
|
|
+ this.$refs[audioId].pause();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onTimeupdateTime(res, playFlag) {
|
|
|
+ if (!res && res !== 0) return;
|
|
|
+ let audioId = this.audioId;
|
|
|
+ this.$refs[audioId].currentTime = res;
|
|
|
+ this.playValue = (res / this.audio.maxTime) * 100;
|
|
|
+ if (playFlag) {
|
|
|
+ let audio = document.getElementsByTagName("audio");
|
|
|
+ audio.forEach((item) => {
|
|
|
+ if (item.id !== audioId) {
|
|
|
+ item.pause();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ this.$refs[audioId].play();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 将整数转换成 时:分:秒的格式
|
|
|
+ realFormatSecond(value) {
|
|
|
+ let theTime = parseInt(value); // 秒
|
|
|
+ let theTime1 = 0; // 分
|
|
|
+ let theTime2 = 0; // 小时
|
|
|
+ if (theTime > 60) {
|
|
|
+ theTime1 = parseInt(theTime / 60);
|
|
|
+ theTime = parseInt(theTime % 60);
|
|
|
+ if (theTime1 > 60) {
|
|
|
+ theTime2 = parseInt(theTime1 / 60);
|
|
|
+ theTime1 = parseInt(theTime1 % 60);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ let result = String(parseInt(theTime));
|
|
|
+ if (result < 10) {
|
|
|
+ result = "0" + result;
|
|
|
+ }
|
|
|
+ if (theTime1 > 0) {
|
|
|
+ result = String(parseInt(theTime1)) + ":" + result;
|
|
|
+ if (theTime1 < 10) {
|
|
|
+ result = "0" + result;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ result = "00:" + result;
|
|
|
+ }
|
|
|
+ if (theTime2 > 0) {
|
|
|
+ result = String(parseInt(theTime2)) + ":" + result;
|
|
|
+ if (theTime2 < 10) {
|
|
|
+ result = "0" + result;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // result = "00:" + result;
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ },
|
|
|
+ handleClickAudio(){
|
|
|
+ this.mp3ListShow = !this.mp3ListShow
|
|
|
+ },
|
|
|
+ handleRepeatAudio(){
|
|
|
+ this.isRepeatAudio = !this.isRepeatAudio
|
|
|
+ },
|
|
|
+ handleSelectAudio(index){
|
|
|
+ this.activeIndex = index
|
|
|
+ this.PlayAudio()
|
|
|
+ },
|
|
|
+ // 下载
|
|
|
+ download() {
|
|
|
+ let userInfor = JSON.parse(getToken());
|
|
|
+ let UserCode = "",
|
|
|
+ UserType = "",
|
|
|
+ SessionID = "";
|
|
|
+ if (userInfor) {
|
|
|
+ UserCode = userInfor.user_code;
|
|
|
+ UserType = userInfor.user_type;
|
|
|
+ SessionID = userInfor.session_id;
|
|
|
+ }
|
|
|
+ let FileID = this.mp3List[this.activeIndex].file_id
|
|
|
+ let data = {
|
|
|
+ SessionID,
|
|
|
+ UserCode,
|
|
|
+ UserType,
|
|
|
+ FileID,
|
|
|
+ };
|
|
|
+ location.href =
|
|
|
+ process.env.VUE_APP_BASE_API +
|
|
|
+ `/GCLSFileServer/WebFileDownload?UserCode=${data.UserCode}&UserType=${data.UserType}&SessionID=${data.SessionID}&FileID=${data.FileID}`;
|
|
|
+ },
|
|
|
+ handleActiveIndex(type){
|
|
|
+ if(type=='-'){
|
|
|
+ if(this.activeIndex!=0){
|
|
|
+ this.activeIndex --
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if(this.activeIndex!=this.mp3List.length-1){
|
|
|
+ this.activeIndex ++
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 生命周期-创建之前
|
|
|
+ beforeCreated() {},
|
|
|
+ // 生命周期-更新之前
|
|
|
+ beforUpdate() {},
|
|
|
+ // 生命周期-销毁之前
|
|
|
+ beforeDestory() {},
|
|
|
+ // 生命周期-销毁完成
|
|
|
+ destoryed() {},
|
|
|
+};
|
|
|
+</script>
|
|
|
+<style lang="scss" scoped>
|
|
|
+/* @import url(); 引入css类 */
|
|
|
+.AudioNNPE {
|
|
|
+ width: 100%;
|
|
|
+ .audioLine {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ background: #ffffff;
|
|
|
+ box-sizing: border-box;
|
|
|
+ border-radius: 8px;
|
|
|
+ .playBox {
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ margin-right: 16px;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ .play {
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ cursor: pointer;
|
|
|
+ display: block;
|
|
|
+ &.playBtn {
|
|
|
+ background: url("../../../assets/common/pause-24-normal-red.png")
|
|
|
+ no-repeat left top;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ }
|
|
|
+ &.pauseBtn {
|
|
|
+ background: url("../../../assets/common/play-24-normal-red.png")
|
|
|
+ no-repeat left top;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .audioName {
|
|
|
+ width: 24px;
|
|
|
+ margin-right: 16px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .loadBtn {
|
|
|
+ background: url("../../../assets/common/loading-red.png") no-repeat left
|
|
|
+ top;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ }
|
|
|
+ .go-start {
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ margin-right: 16px;
|
|
|
+ cursor: pointer;
|
|
|
+ display: block;
|
|
|
+ background: url("../../../assets/common/go-start.png") no-repeat left top;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ &.disabled {
|
|
|
+ background: url("../../../assets/common/go-start-disabled.png")
|
|
|
+ no-repeat left top;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ cursor: not-allowed;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .go-end {
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ margin-right: 16px;
|
|
|
+ cursor: pointer;
|
|
|
+ display: block;
|
|
|
+ background: url("../../../assets/common/go-end.png") no-repeat left top;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ &.disabled {
|
|
|
+ background: url("../../../assets/common/go-end-disabled.png") no-repeat
|
|
|
+ left top;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ cursor: not-allowed;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .play-mode {
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ margin-right: 16px;
|
|
|
+ cursor: pointer;
|
|
|
+ display: block;
|
|
|
+ &.order {
|
|
|
+ background: url("../../../assets/common/auto-24-disable-black.png")
|
|
|
+ no-repeat left top;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ }
|
|
|
+ &.roll {
|
|
|
+ background: url("../../../assets/common/Repeat-24-normal-red.png")
|
|
|
+ no-repeat left top;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .time-box{
|
|
|
+ min-width: 60px;
|
|
|
+ text-align: right;
|
|
|
+ margin-right: 8px;
|
|
|
+ }
|
|
|
+ .common-btn {
|
|
|
+ width: 40px;
|
|
|
+ height: 40px;
|
|
|
+ margin: 0 8px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ border-radius: 8px;
|
|
|
+ position: relative;
|
|
|
+ cursor: pointer;
|
|
|
+ &.audio-btn.active {
|
|
|
+ background: #eeeeee;
|
|
|
+ }
|
|
|
+ > img {
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ }
|
|
|
+ .audioList{
|
|
|
+ position: absolute;
|
|
|
+ top: 63px;
|
|
|
+ left: -40px;
|
|
|
+ width: 120px;
|
|
|
+ max-height: 280px;
|
|
|
+ overflow: auto;
|
|
|
+ background: #FFFFFF;
|
|
|
+ box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
+ border-radius: 8px;
|
|
|
+ z-index: 1;
|
|
|
+ li{
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 8px 16px;
|
|
|
+ width: 100%;
|
|
|
+ :nth-child(1){
|
|
|
+ width: 24px;
|
|
|
+ color: #000000;
|
|
|
+ font-size: 16px;
|
|
|
+ line-height: 24px;
|
|
|
+ }
|
|
|
+ :nth-child(2){
|
|
|
+ color: rgba(0, 0, 0, 0.4);
|
|
|
+ font-size: 16px;
|
|
|
+ line-height: 24px;
|
|
|
+ flex: 1;
|
|
|
+ text-align: right;
|
|
|
+ margin: 0;
|
|
|
+ }
|
|
|
+ &:hover,&.active{
|
|
|
+ background: #EEEEEE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|
|
|
+<style lang="scss">
|
|
|
+.AudioNNPE {
|
|
|
+ .el-slider__button-wrapper {
|
|
|
+ position: relative;
|
|
|
+ z-index: 0;
|
|
|
+ }
|
|
|
+ .el-slider__button {
|
|
|
+ width: 8px;
|
|
|
+ height: 8px;
|
|
|
+ top: 12px;
|
|
|
+ position: absolute;
|
|
|
+ }
|
|
|
+ .el-slider__runway {
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+ background: #e5e5e5;
|
|
|
+ border-radius: 0px;
|
|
|
+ height: 2px;
|
|
|
+ }
|
|
|
+ .el-slider {
|
|
|
+ position: relative;
|
|
|
+ }
|
|
|
+ .el-slider__bar {
|
|
|
+ height: 2px;
|
|
|
+ background: #DE4444;
|
|
|
+ }
|
|
|
+ .el-slider__button {
|
|
|
+ background: #DE4444;
|
|
|
+ border: none;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|