guanchunjie %!s(int64=3) %!d(string=hai) anos
pai
achega
f6f92687b8

BIN=BIN
src/assets/NPC/loading-red.png


BIN=BIN
src/assets/NPC/tts-loading.png


+ 1 - 0
src/components/Adult/preview/ArticleViewChs/NormalModelChs.vue

@@ -11,6 +11,7 @@
         audioId="artNormalAudio"
         :mp3="curQue.mp3_list[0].id"
         :getCurTime="getCurTime"
+        :duration="curQue.mp3_list[0].media_duration"
         ref="audioLine"
       />
     </div>

+ 431 - 0
src/components/Adult/preview/AudioLine copy.vue

@@ -0,0 +1,431 @@
+<template>
+  <div class="Audio">
+    <div class="audioLine" v-if="!hideSlider">
+      <div
+        class="play"
+        :class="audio.playing ? 'playBtn' : 'pauseBtn'"
+        @click="PlayAudio"
+      />
+      <template v-if="!isRepeat">
+        <el-slider
+          v-model="playValue"
+          :style="{ width: sliderWidth + 'px', height: '2px' }"
+          :format-tooltip="formatProcessToolTip"
+          @change="changeCurrentTime"
+        />
+        <span
+          ><template v-if="audio.playing">-</template
+          >{{
+            audio.maxTime
+              ? realFormatSecond(audio.maxTime - audio.currentTime)
+              : ""
+          }}</span
+        >
+      </template>
+      <audio
+        ref="audio"
+        :src="mp3"
+        @loadedmetadata="onLoadedmetadata"
+        @timeupdate="onTimeupdate"
+      />
+    </div>
+    <div class="audioLine2" v-else>
+      <div
+        class="play-icon"
+        :class="audio.playing ? 'playBtn-icon' : 'pauseBtn-icon'"
+        @click="PlayAudio"
+      />
+    </div>
+    <audio
+      :ref="audioId"
+      :src="mp3"
+      @loadedmetadata="onLoadedmetadata"
+      @timeupdate="onTimeupdate"
+      @canplay="oncanplay"
+      :id="audioId"
+    />
+  </div>
+</template>
+
+<script>
+// 这里可以导入其它文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
+// 例如:import 《组件名称》from ‘《组件路径》';
+export default {
+  // import引入的组件需要注入到对象中才能使用
+  components: {},
+  props: [
+    "mp3",
+    "getCurTime",
+    "stopAudio",
+    "width",
+    "isRepeat",
+    "themeColor",
+    "hideSlider",
+    "ed",
+    "bg",
+    "audioId",
+  ],
+  data() {
+    // 这里存放数据
+    return {
+      playValue: 0,
+      audio: {
+        // 该字段是音频是否处于播放状态的属性
+        playing: false,
+        // 音频当前播放时长
+        currentTime: 0,
+        // 音频最大播放时长
+        maxTime: 0,
+        isPlaying: false,
+        loading: false,
+      },
+      audioAllTime: null, // 展示总时间
+      duioCurrentTime: null, // 剩余时间
+    };
+  },
+  // 计算属性 类似于data概念
+  computed: {
+    sliderWidth() {
+      let width = 0;
+      if (this.width) {
+        width = this.width;
+      } else {
+        width = 662;
+      }
+      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("play", function () {
+      _this.audio.playing = true;
+      _this.audio.isPlaying = true;
+    });
+    _this.$refs[audioId].addEventListener("pause", function () {
+      _this.audio.playing = false;
+    });
+    _this.$refs[audioId].addEventListener("ended", function () {
+      _this.audio.playing = false;
+      _this.audio.isPlaying = false;
+    });
+    this.$nextTick(() => {
+      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.mp3) {
+          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);
+      } else {
+        if (this.hideSlider) {
+          this.$refs[audioId].play();
+          this.onTimeupdateTime(this.bg / 1000);
+        } else {
+          this.$refs[audioId].play();
+        }
+        this.audio.playing = true;
+        this.$emit("handleChangeStopAudio");
+        this.$emit("handleListenRead", true);
+      }
+    },
+    oncanplay() {},
+    // 点击 拖拽播放音频
+    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.audioAllTime = this.realFormatSecond(this.audio.maxTime);
+    },
+    // 当音频当前时间改变后,进度条也要改变
+    onTimeupdate(res) {
+      let audioId = this.audioId;
+      this.audio.currentTime = res.target.currentTime;
+      this.getCurTime(res.target.currentTime);
+      this.playValue = (this.audio.currentTime / this.audio.maxTime) * 100;
+      if (this.audio.currentTime * 1000 > this.ed) {
+        this.$refs[audioId].pause();
+      }
+    },
+    onTimeupdateTime(res, playFlag) {
+      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;
+    },
+  },
+  // 生命周期-创建之前
+  beforeCreated() {},
+  // 生命周期-更新之前
+  beforUpdate() {},
+  // 生命周期-销毁之前
+  beforeDestory() {},
+  // 生命周期-销毁完成
+  destoryed() {},
+};
+</script>
+<style lang="scss" scoped>
+/* @import url(); 引入css类 */
+.Audio {
+  width: 100%;
+  .audioLine {
+    display: flex;
+    align-items: center;
+    width: 100%;
+    height: 40px;
+    background: #ffffff;
+    // border: 1px solid rgba(0, 0, 0, 0.1);
+    // box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.1);
+    box-sizing: border-box;
+    border-radius: 4px;
+    .play {
+      margin-right: 12px;
+      margin-left: 8px;
+      width: 16px;
+      height: 16px;
+      cursor: pointer;
+      display: block;
+      // &.playBtn {
+      //   background: url("../../../assets/pause.png") no-repeat left top;
+      //   background-size: 100% 100%;
+      // }
+      // &.pauseBtn {
+      //   background: url("../../../assets/play.png") no-repeat left top;
+      //   background-size: 100% 100%;
+      // }
+    }
+
+    span {
+      font-size: 16px;
+      line-height: 19px;
+      color: #000;
+      margin-left: 8px;
+      margin-right: 12px;
+      min-width: 56px;
+      text-align: right;
+    }
+  }
+  > .audioLine2 {
+    .play-icon {
+      width: 16px;
+      height: 16px;
+      cursor: pointer;
+      &.playBtn-icon {
+        background: url("../../../assets/NPC/icon-voice-play-red.png") no-repeat
+          left top;
+        background-size: 100% 100%;
+      }
+      &.pauseBtn-icon {
+        background: url("../../../assets/NPC/play-red.png") no-repeat left top;
+        background-size: 100% 100%;
+      }
+    }
+  }
+}
+.NPC-Big-Book-preview-green {
+  .playBtn-icon {
+    background: url("../../../assets/NPC/icon-voice-play-green.png") no-repeat
+      left top;
+    background-size: 100% 100%;
+  }
+  .pauseBtn-icon {
+    background: url("../../../assets/NPC/play-green.png") no-repeat left top;
+    background-size: 100% 100%;
+  }
+}
+.NPC-Big-Book-preview-red {
+  .playBtn-icon {
+    background: url("../../../assets/NPC/icon-voice-play-red.png") no-repeat
+      left top;
+    background-size: 100% 100%;
+  }
+  .pauseBtn-icon {
+    background: url("../../../assets/NPC/play-red.png") no-repeat left top;
+    background-size: 100% 100%;
+  }
+}
+.NPC-Big-Book-preview-brown {
+  .playBtn-icon {
+    background: url("../../../assets/NPC/icon-voice-play-brown.png") no-repeat
+      left top;
+    background-size: 100% 100%;
+  }
+  .pauseBtn-icon {
+    background: url("../../../assets/NPC/play-brown.png") no-repeat left top;
+    background-size: 100% 100%;
+  }
+}
+</style>
+<style lang="scss">
+.Audio {
+  .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: rgba(118, 99, 236, 1);
+  }
+  .el-slider__button {
+    background: rgba(118, 99, 236, 1);
+    border: none;
+  }
+}
+.NPC-Book-Sty {
+  .Audio {
+    .el-slider__bar {
+      height: 2px;
+      background: #de4444;
+    }
+    .el-slider__button {
+      background: #de4444;
+      border: none;
+    }
+  }
+}
+.NPC-Big-Book-preview-green {
+  .Audio {
+    .el-slider__bar {
+      background: #24b99e !important;
+    }
+    .el-slider__button {
+      background: #24b99e !important;
+    }
+  }
+}
+.NPC-Big-Book-preview-brown {
+  .Audio {
+    .el-slider__bar {
+      background: #bd8865 !important;
+    }
+    .el-slider__button {
+      background: #bd8865 !important;
+    }
+  }
+}
+</style>

+ 24 - 8
src/components/Adult/preview/AudioLine.vue

@@ -3,7 +3,9 @@
     <div class="audioLine" v-if="!hideSlider">
       <div
         class="play"
-        :class="audio.playing ? 'playBtn' : 'pauseBtn'"
+        :class="
+          audio.loading ? 'loadBtn' : audio.playing ? 'playBtn' : 'pauseBtn'
+        "
         @click="PlayAudio"
       />
       <template v-if="!isRepeat">
@@ -22,12 +24,6 @@
           }}</span
         >
       </template>
-      <audio
-        ref="audio"
-        :src="mp3"
-        @loadedmetadata="onLoadedmetadata"
-        @timeupdate="onTimeupdate"
-      />
     </div>
     <div class="audioLine2" v-else>
       <div
@@ -41,6 +37,8 @@
       :src="mp3"
       @loadedmetadata="onLoadedmetadata"
       @timeupdate="onTimeupdate"
+      @canplaythrough="oncanplaythrough"
+      preload="meta"
       :id="audioId"
     />
   </div>
@@ -76,6 +74,7 @@ export default {
         // 音频最大播放时长
         maxTime: 0,
         isPlaying: false,
+        loading: false,
       },
       audioAllTime: null, // 展示总时间
       duioCurrentTime: null, // 剩余时间
@@ -119,7 +118,11 @@ export default {
   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;
     });
@@ -130,6 +133,7 @@ export default {
       _this.audio.playing = false;
       _this.audio.isPlaying = false;
     });
+
     this.$nextTick(() => {
       document
         .getElementsByClassName("el-slider__button-wrapper")[0]
@@ -165,17 +169,24 @@ export default {
         this.audio.playing = false;
         this.$emit("handleListenRead", 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.audio.playing = true;
         this.$emit("handleChangeStopAudio");
         this.$emit("handleListenRead", true);
       }
     },
+    oncanplaythrough() {
+      console.log("音频加载完成");
+      this.audio.loading = false;
+    },
     // 点击 拖拽播放音频
     changeCurrentTime(value) {
       let audioId = this.audioId;
@@ -291,6 +302,11 @@ export default {
       height: 16px;
       cursor: pointer;
       display: block;
+      &.loadBtn {
+        background: url("../../../assets/NPC/loading-red.png") no-repeat left
+          top;
+        background-size: 100% 100%;
+      }
       // &.playBtn {
       //   background: url("../../../assets/pause.png") no-repeat left top;
       //   background-size: 100% 100%;

+ 2 - 1
vue.config.js

@@ -42,7 +42,8 @@ module.exports = {
       // change xxx-api/login => mock/login
       // detail: https://cli.vuejs.org/config/#devserver-proxy
       [process.env.VUE_APP_BASE_API]: {
-        target: `http://gcls.utschool.cn/`,
+        //target: `http://gcls.utschool.cn/`,
+        target: `http://gcls.helxsoft.cn/`,
         changeOrigin: true,
         pathRewrite: {
           ['^' + process.env.VUE_APP_BASE_API]: ''