Browse Source

语音全屏

guanchunjie 4 years ago
parent
commit
6f8f528e0f
74 changed files with 2216 additions and 157 deletions
  1. BIN
      src/assets/NPC/compare-disable-24.png
  2. BIN
      src/assets/NPC/compare-pause-blue-24.png
  3. BIN
      src/assets/NPC/compare-pause-brown-24.png
  4. BIN
      src/assets/NPC/compare-pause-green-24.png
  5. BIN
      src/assets/NPC/compare-pause-orange-24.png
  6. BIN
      src/assets/NPC/compare-pause-red-24.png
  7. BIN
      src/assets/NPC/del-24.png
  8. BIN
      src/assets/NPC/left-black.png
  9. BIN
      src/assets/NPC/left-grey.png
  10. BIN
      src/assets/NPC/left-white.png
  11. BIN
      src/assets/NPC/pause-24-normal-Orange.png
  12. BIN
      src/assets/NPC/pause-24-normal-blue.png
  13. BIN
      src/assets/NPC/pause-24-normal-brown.png
  14. BIN
      src/assets/NPC/pause-24-normal-green.png
  15. BIN
      src/assets/NPC/pause-24-normal-red.png
  16. BIN
      src/assets/NPC/right-black.png
  17. BIN
      src/assets/NPC/right-grey.png
  18. BIN
      src/assets/NPC/right-white.png
  19. BIN
      src/assets/NPC/vocie-gif.png
  20. BIN
      src/assets/NPC/voice-24.png
  21. BIN
      src/assets/icon/EN-24-disable-Black.png
  22. BIN
      src/assets/icon/EN-24-normal-Blue.png
  23. BIN
      src/assets/icon/EN-24-normal-Brown.png
  24. BIN
      src/assets/icon/EN-24-normal-Green.png
  25. BIN
      src/assets/icon/EN-24-normal-Orange.png
  26. BIN
      src/assets/icon/EN-24-normal-Purple.png
  27. BIN
      src/assets/icon/EN-24-normal-Red.png
  28. BIN
      src/assets/icon/EN-24-normal-yellow.png
  29. BIN
      src/assets/icon/Repeat-24-disable-Black.png
  30. BIN
      src/assets/icon/Repeat-24-normal-Blue.png
  31. BIN
      src/assets/icon/Repeat-24-normal-Brown.png
  32. BIN
      src/assets/icon/Repeat-24-normal-Green.png
  33. BIN
      src/assets/icon/Repeat-24-normal-Orange.png
  34. BIN
      src/assets/icon/Repeat-24-normal-red.png
  35. BIN
      src/assets/icon/Repeat-24-normal-yellow.png
  36. BIN
      src/assets/icon/bookmarkfill-24-disable-Black.png
  37. BIN
      src/assets/icon/bookmarkfill-24-normal-blue.png
  38. BIN
      src/assets/icon/bookmarkfill-24-normal-brown.png
  39. BIN
      src/assets/icon/bookmarkfill-24-normal-green.png
  40. BIN
      src/assets/icon/bookmarkfill-24-normal-red.png
  41. BIN
      src/assets/icon/bookmarkfill-24-normal-yellow.png
  42. BIN
      src/assets/icon/cross-24-normal-black.png
  43. BIN
      src/assets/icon/cross-24-normal-white.png
  44. BIN
      src/assets/icon/pause-24-normal-Black.png
  45. BIN
      src/assets/icon/pause-24-normal-Orange.png
  46. BIN
      src/assets/icon/pause-24-normal-blue.png
  47. BIN
      src/assets/icon/pause-24-normal-brown.png
  48. BIN
      src/assets/icon/pause-24-normal-green.png
  49. BIN
      src/assets/icon/pause-24-normal-red.png
  50. BIN
      src/assets/icon/pause-24-normal-white.png
  51. BIN
      src/assets/icon/pauseC-24-normal-Blue.png
  52. BIN
      src/assets/icon/pauseC-24-normal-Brown.png
  53. BIN
      src/assets/icon/pauseC-24-normal-Green.png
  54. BIN
      src/assets/icon/pauseC-24-normal-Orangepng.png
  55. BIN
      src/assets/icon/pauseC-24-normal-red.png
  56. BIN
      src/assets/icon/pinyin-24-disable-Black.png
  57. BIN
      src/assets/icon/pinyin-24-normal-brown.png
  58. BIN
      src/assets/icon/pinyin-24-normal-green.png
  59. BIN
      src/assets/icon/pinyin-24-normal-orange.png
  60. BIN
      src/assets/icon/pinyin-24-normal-red.png
  61. BIN
      src/assets/icon/pinyin-24-normal-yellow.png
  62. BIN
      src/assets/icon/play-24-normal-Black.png
  63. BIN
      src/assets/icon/play-24-normal-white.png
  64. 33 4
      src/components/Adult/preview/AudioCompare.vue
  65. 24 15
      src/components/Adult/preview/AudioLine.vue
  66. 486 0
      src/components/Adult/preview/AudioLineSentence.vue
  67. 53 2
      src/components/Adult/preview/DialogueArticleViewChs/Practicechs.vue
  68. 476 0
      src/components/Adult/preview/Soundrecorddiff.vue
  69. 998 0
      src/components/Adult/preview/Voicefullscreen.vue
  70. 20 15
      src/components/Adult/preview/components/AudioRed.vue
  71. 57 14
      src/components/Adult/preview/components/Wordcard.vue
  72. 1 11
      src/styles/index.scss
  73. 5 2
      src/views/adultInput.vue
  74. 63 94
      src/views/courseList.vue

BIN
src/assets/NPC/compare-disable-24.png


BIN
src/assets/NPC/compare-pause-blue-24.png


BIN
src/assets/NPC/compare-pause-brown-24.png


BIN
src/assets/NPC/compare-pause-green-24.png


BIN
src/assets/NPC/compare-pause-orange-24.png


BIN
src/assets/NPC/compare-pause-red-24.png


BIN
src/assets/NPC/del-24.png


BIN
src/assets/NPC/left-black.png


BIN
src/assets/NPC/left-grey.png


BIN
src/assets/NPC/left-white.png


BIN
src/assets/NPC/pause-24-normal-Orange.png


BIN
src/assets/NPC/pause-24-normal-blue.png


BIN
src/assets/NPC/pause-24-normal-brown.png


BIN
src/assets/NPC/pause-24-normal-green.png


BIN
src/assets/NPC/pause-24-normal-red.png


BIN
src/assets/NPC/right-black.png


BIN
src/assets/NPC/right-grey.png


BIN
src/assets/NPC/right-white.png


BIN
src/assets/NPC/vocie-gif.png


BIN
src/assets/NPC/voice-24.png


BIN
src/assets/icon/EN-24-disable-Black.png


BIN
src/assets/icon/EN-24-normal-Blue.png


BIN
src/assets/icon/EN-24-normal-Brown.png


BIN
src/assets/icon/EN-24-normal-Green.png


BIN
src/assets/icon/EN-24-normal-Orange.png


BIN
src/assets/icon/EN-24-normal-Purple.png


BIN
src/assets/icon/EN-24-normal-Red.png


BIN
src/assets/icon/EN-24-normal-yellow.png


BIN
src/assets/icon/Repeat-24-disable-Black.png


BIN
src/assets/icon/Repeat-24-normal-Blue.png


BIN
src/assets/icon/Repeat-24-normal-Brown.png


BIN
src/assets/icon/Repeat-24-normal-Green.png


BIN
src/assets/icon/Repeat-24-normal-Orange.png


BIN
src/assets/icon/Repeat-24-normal-red.png


BIN
src/assets/icon/Repeat-24-normal-yellow.png


BIN
src/assets/icon/bookmarkfill-24-disable-Black.png


BIN
src/assets/icon/bookmarkfill-24-normal-blue.png


BIN
src/assets/icon/bookmarkfill-24-normal-brown.png


BIN
src/assets/icon/bookmarkfill-24-normal-green.png


BIN
src/assets/icon/bookmarkfill-24-normal-red.png


BIN
src/assets/icon/bookmarkfill-24-normal-yellow.png


BIN
src/assets/icon/cross-24-normal-black.png


BIN
src/assets/icon/cross-24-normal-white.png


BIN
src/assets/icon/pause-24-normal-Black.png


BIN
src/assets/icon/pause-24-normal-Orange.png


BIN
src/assets/icon/pause-24-normal-blue.png


BIN
src/assets/icon/pause-24-normal-brown.png


BIN
src/assets/icon/pause-24-normal-green.png


BIN
src/assets/icon/pause-24-normal-red.png


BIN
src/assets/icon/pause-24-normal-white.png


BIN
src/assets/icon/pauseC-24-normal-Blue.png


BIN
src/assets/icon/pauseC-24-normal-Brown.png


BIN
src/assets/icon/pauseC-24-normal-Green.png


BIN
src/assets/icon/pauseC-24-normal-Orangepng.png


BIN
src/assets/icon/pauseC-24-normal-red.png


BIN
src/assets/icon/pinyin-24-disable-Black.png


BIN
src/assets/icon/pinyin-24-normal-brown.png


BIN
src/assets/icon/pinyin-24-normal-green.png


BIN
src/assets/icon/pinyin-24-normal-orange.png


BIN
src/assets/icon/pinyin-24-normal-red.png


BIN
src/assets/icon/pinyin-24-normal-yellow.png


BIN
src/assets/icon/play-24-normal-Black.png


BIN
src/assets/icon/play-24-normal-white.png


+ 33 - 4
src/components/Adult/preview/AudioCompare.vue

@@ -2,7 +2,10 @@
 <template>
   <div class="compara-content">
     <template v-if="wavblob">
-      <div style="width: 16px; height: 16px; margin-left: 8px" v-if="!isR">
+      <div
+        :class="type == 'full' ? 'compare-box-big' : 'compare-box'"
+        v-if="!isR"
+      >
         <AudioLine
           :mp3="url"
           :getCurTime="getCurTime"
@@ -15,22 +18,31 @@
           :ed="ed"
           @handleChangeStopAudio="handleChangeStopAudio"
           @sentPause="sentPause"
+          :type="type"
         />
       </div>
-      <div style="width: 16px; height: 16px; margin-left: 8px" v-else>
+      <div :class="type == 'full' ? 'compare-box-big' : 'compare-box'" v-else>
         <audio-red
           v-if="sentIndex == index"
           :mp3="wavblob"
           :isCompare="true"
           :themeColor="themeColor"
           @sentPause="sentPause"
+          :type="type"
         />
       </div>
     </template>
     <template v-else>
       <img
-        src="../../../assets/NPC/compare-disable.png"
-        class="compare-disable"
+        :src="
+          type == 'full'
+            ? require('../../../assets/NPC/compare-disable-24.png')
+            : require('../../../assets/NPC/compare-disable.png')
+        "
+        :class="[
+          'compare-disable',
+          type == 'full' ? 'compare-disable-big' : '',
+        ]"
       />
     </template>
   </div>
@@ -57,6 +69,7 @@ export default {
     "stopAudio",
     "handleChangeStopAudio",
     "themeColor",
+    "type",
   ],
   data() {
     return {
@@ -91,10 +104,26 @@ export default {
 </script>
 <style lang='scss' scoped>
 //@import url(); 引入公共css类
+.compare-box {
+  width: 16px;
+  height: 16px;
+  margin-left: 8px;
+  &-big {
+    width: 24px;
+    height: 24px;
+    margin-left: 0px;
+  }
+}
 .compare-disable {
   width: 16px;
   height: 16px;
   display: block;
   margin-left: 8px;
+  &-big {
+    width: 24px;
+    height: 24px;
+    display: block;
+    margin-left: 0px;
+  }
 }
 </style>

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

@@ -27,14 +27,15 @@
     </div>
     <div v-else class="audioLine2">
       <div
-        class="play-icon"
-        :class="
+        :class="[
+          'play-icon',
           audio.loading
             ? 'loadBtn'
             : audio.playing
             ? 'playBtn-icon'
-            : 'pauseBtn-icon'
-        "
+            : 'pauseBtn-icon',
+          type == 'full' ? 'play-icon-big' : '',
+        ]"
         @click="PlayAudio"
       />
     </div>
@@ -68,6 +69,7 @@ export default {
     "ed",
     "bg",
     "audioId",
+    "type",
   ],
   data() {
     // 这里存放数据
@@ -339,14 +341,18 @@ export default {
       width: 16px;
       height: 16px;
       cursor: pointer;
+      &-big {
+        width: 24px;
+        height: 24px;
+      }
       &.playBtn-icon {
-        background: url("../../../assets/icon/pauseC-16-normal-red.png")
+        background: url("../../../assets/icon/pauseC-24-normal-red.png")
           no-repeat left top;
         background-size: 100% 100%;
       }
       &.pauseBtn-icon {
-        background: url("../../../assets/NPC/compare-pause-red.png") no-repeat
-          left top;
+        background: url("../../../assets/NPC/compare-pause-red-24.png")
+          no-repeat left top;
         background-size: 100% 100%;
       }
     }
@@ -359,6 +365,17 @@ export default {
 </style>
 <style lang="scss">
 .Audio {
+  .el-slider__bar {
+    height: 2px;
+    background: #de4444;
+  }
+  .el-slider__button {
+    background: #de4444;
+    border: none;
+  }
+  .el-slider__button-wrapper {
+    width: 25px;
+  }
   .el-slider__button-wrapper {
     position: relative;
     z-index: 0;
@@ -379,14 +396,6 @@ export default {
   .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 {

+ 486 - 0
src/components/Adult/preview/AudioLineSentence.vue

@@ -0,0 +1,486 @@
+<template>
+  <div
+    :class="[
+      'Audio',
+      'AudioFull',
+      mp3Source && mp3Source == 'tts' ? 'Audio-tts' : '',
+    ]"
+  >
+    <div v-if="!hideSlider" class="audioLine">
+      <div
+        class="play"
+        :class="[
+          audio.loading ? 'loadBtn' : audio.playing ? 'playBtn' : 'pauseBtn',
+        ]"
+        @click="PlayAudio"
+      />
+      <template>
+        <el-slider
+          v-model="playValue"
+          :style="{ width: sliderWidth + 'px', height: '6px' }"
+          :format-tooltip="formatProcessToolTip"
+          @change="changeCurrentTime"
+        />
+        <span>
+          {{ realFormatSecond(audio.maxTime) }}
+          <!-- <template v-if="audio.playing">-</template
+          >{{
+            audio.maxTime
+              ? realFormatSecond(audio.maxTime - audio.currentTime - bg / 1000)
+              : ""
+          }} -->
+        </span>
+      </template>
+    </div>
+    <div v-else class="audioLine2">
+      <div
+        class="play-icon"
+        :class="
+          audio.loading
+            ? 'loadBtn'
+            : audio.playing
+            ? 'playBtn-icon'
+            : 'pauseBtn-icon'
+        "
+        @click="PlayAudio"
+      />
+    </div>
+    <audio
+      :id="audioId"
+      :ref="audioId"
+      :src="mp3"
+      preload="meta"
+      @loadedmetadata="onLoadedmetadata"
+      @timeupdate="onTimeupdate"
+      @canplaythrough="oncanplaythrough"
+    />
+  </div>
+</template>
+
+<script>
+// 这里可以导入其它文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
+// 例如:import 《组件名称》from ‘《组件路径》';
+export default {
+  // import引入的组件需要注入到对象中才能使用
+  components: {},
+  props: [
+    "mp3",
+    "mp3Source",
+    "getCurTime",
+    "stopAudio",
+    "width",
+    "isRepeat",
+    "themeColor",
+    "ed",
+    "bg",
+    "audioId",
+    "maxTime",
+    "hideSlider",
+    "bgIndex",
+  ],
+  data() {
+    // 这里存放数据
+    return {
+      playValue: 0,
+      audio: {
+        // 该字段是音频是否处于播放状态的属性
+        playing: false,
+        // 音频当前播放时长
+        currentTime: 0,
+        // 音频最大播放时长
+        maxTime: 0,
+        isPlaying: false,
+        loading: false,
+      },
+      playTime: parseInt(this.maxTime),
+      audioAllTime: null, // 展示总时间
+      duioCurrentTime: null, // 剩余时间
+      count: 0,
+      loading: 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("loadstart", function () {});
+    _this.$refs[audioId].addEventListener("play", function () {
+      _this.audio.playing = true;
+      _this.audio.isPlaying = true;
+      _this.audio.loading = false;
+    });
+    _this.$refs[audioId].addEventListener("pause", function () {
+      _this.audio.playing = false;
+      if (_this.audio.currentTime * 1000 + 500 > _this.ed) {
+        //_this.$emit("sentPause", true);
+        _this.playValue = 0;
+      }
+    });
+    _this.$refs[audioId].addEventListener("ended", function () {
+      _this.audio.playing = false;
+      _this.audio.isPlaying = false;
+      _this.$emit("handleListenRead", 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();
+        }
+      });
+      let video = document.getElementsByTagName("video");
+      video.forEach((vItem) => {
+        vItem.pause();
+      });
+
+      if (this.audio.playing) {
+        this.$refs[audioId].pause();
+        this.audio.playing = false;
+        this.$emit("handleListenRead", false);
+      } else {
+        if (this.count == 0) {
+          this.audio.loading = true;
+          this.count++;
+        }
+
+        this.$refs[audioId].play();
+        this.onTimeupdateTime(this.bg / 1000);
+
+        this.$emit("handleChangeStopAudio");
+        this.$emit("handleListenRead", true);
+      }
+    },
+    oncanplaythrough() {
+      let _this = this;
+      // setTimeout(() => {
+      _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(this.maxTime);
+      //this.audio.maxTime = parseInt(res.target.duration);
+      //this.playTime = parseInt(this.maxTime);
+      //this.audioAllTime = this.realFormatSecond(this.audio.maxTime);
+    },
+    // 当音频当前时间改变后,进度条也要改变
+    onTimeupdate(res) {
+      let _this = this;
+      let audioId = _this.audioId;
+      _this.audio.currentTime = res.target.currentTime;
+      _this.getCurTime(res.target.currentTime);
+      let time = _this.audio.currentTime - _this.bg / 1000;
+      _this.playValue = (time / _this.audio.maxTime) * 100;
+      console.log(time, _this.audio.maxTime, _this.playValue);
+      setTimeout(() => {
+        if (_this.audio.currentTime * 1000 > _this.ed) {
+          _this.$refs[audioId].pause();
+        }
+      }, 50);
+    },
+    onTimeupdateTime(res, playFlag) {
+      if (!res) return;
+      let audioId = this.audioId;
+      this.$refs[audioId].currentTime = res;
+      let time = res - this.bg / 1000;
+      this.playValue = (time / 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类 */
+.AudioFull {
+  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;
+      min-width: 16px;
+      height: 16px;
+      cursor: pointer;
+      display: block;
+    }
+
+    span {
+      font-size: 16px;
+      line-height: 19px;
+      color: #000;
+      margin-left: 8px;
+      margin-right: 12px;
+      font-weight: bold;
+      font-size: 16px;
+      line-height: 24px;
+      text-align: right;
+    }
+  }
+  .audioLine2 {
+    .play-icon {
+      width: 16px;
+      height: 16px;
+      cursor: pointer;
+      &.playBtn-icon {
+        background: url("../../../assets/icon/pauseC-16-normal-red.png")
+          no-repeat left top;
+        background-size: 100% 100%;
+      }
+      &.pauseBtn-icon {
+        background: url("../../../assets/NPC/compare-pause-red.png") no-repeat
+          left top;
+        background-size: 100% 100%;
+      }
+    }
+  }
+  .loadBtn {
+    background: url("../../../assets/NPC/loading-red.png") no-repeat left top;
+    background-size: 100% 100%;
+  }
+}
+</style>
+<style lang="scss">
+.AudioFull {
+  .el-slider__button-wrapper {
+    position: relative;
+    z-index: 0;
+  }
+  .el-slider__button {
+    width: 6px;
+    height: 12px;
+    border-radius: 6px;
+    top: 12px;
+    position: absolute;
+  }
+  .el-slider__runway {
+    margin: 0;
+    padding: 0;
+    background: #e5e5e5;
+    border-radius: 6px;
+    height: 6px;
+  }
+  .el-slider {
+    position: relative;
+  }
+  .el-slider__bar {
+    height: 6px;
+    border-radius: 6px 0 0 6px;
+    background: #de4444;
+  }
+  .el-slider__button {
+    background: #de4444;
+    border: none;
+  }
+  .el-slider__button-wrapper {
+    width: 25px;
+  }
+}
+.NPC-Book-Sty {
+  .AudioFull {
+    .el-slider__bar {
+      height: 6px;
+      border-radius: 6px;
+      background: #de4444;
+    }
+    .el-slider__button {
+      background: #de4444;
+      border: none;
+    }
+  }
+}
+.NPC-Big-Book-preview-green {
+  .AudioFull {
+    .el-slider__bar {
+      background: #24b99e !important;
+    }
+    .el-slider__button {
+      background: #24b99e !important;
+    }
+    .audioLine2 {
+      .play-icon {
+        &.playBtn-icon {
+          background: url("../../../assets/icon/pauseC-16-normal-Green.png")
+            no-repeat left top;
+          background-size: 100% 100%;
+        }
+        &.pauseBtn-icon {
+          background: url("../../../assets/NPC/compare-pause-green.png")
+            no-repeat left top;
+          background-size: 100% 100%;
+        }
+      }
+    }
+    .loadBtn {
+      background: url("../../../assets/NPC/loading-green.png") no-repeat left
+        top;
+      background-size: 100% 100%;
+    }
+  }
+}
+.NPC-Big-Book-preview-brown {
+  .AudioFull {
+    .el-slider__bar {
+      background: #bd8865 !important;
+    }
+    .el-slider__button {
+      background: #bd8865 !important;
+    }
+    .audioLine2 {
+      .play-icon {
+        &.playBtn-icon {
+          background: url("../../../assets/icon/pauseC-16-normal-Brown.png")
+            no-repeat left top;
+          background-size: 100% 100%;
+        }
+        &.pauseBtn-icon {
+          background: url("../../../assets/NPC/compare-pause-brown.png")
+            no-repeat left top;
+          background-size: 100% 100%;
+        }
+      }
+    }
+    .loadBtn {
+      background: url("../../../assets/NPC/loading-brown.png") no-repeat left
+        top;
+      background-size: 100% 100%;
+    }
+  }
+}
+</style>

+ 53 - 2
src/components/Adult/preview/DialogueArticleViewChs/Practicechs.vue

@@ -352,10 +352,22 @@
                 />
               </div>
             </div>
+            <span class="full-screen-icon" @click="fullScreen"> </span>
           </div>
         </div>
       </div>
     </template>
+    <div class="voice-full-screen" v-if="isFull && resObj">
+      <Voicefullscreen
+        :themeColor="themeColor"
+        :curQue="curQue"
+        :sentList="resObj.sentList"
+        :sentIndex="sentIndex"
+        :mp3="curQue.mp3_list[0].id"
+        :noFont="noFont"
+        @exitFullscreen="exitFullscreen"
+      />
+    </div>
   </div>
 </template>
 
@@ -365,6 +377,7 @@ import AudioLine from "../AudioLine.vue";
 import Soundrecord from "../../preview/Soundrecord.vue"; // 录音模板
 import RoleChs from "./RoleChs.vue";
 import AudioCompare from "../AudioCompare.vue";
+import Voicefullscreen from "../Voicefullscreen.vue";
 export default {
   name: "ArticleView",
   props: ["curQue", "colorBox", "noFont", "themeColor", "isShowEN"],
@@ -373,6 +386,7 @@ export default {
     Soundrecord,
     RoleChs,
     AudioCompare,
+    Voicefullscreen,
   },
   filters: {
     handlePinyin(wordsList) {
@@ -433,6 +447,7 @@ export default {
       isRepeat: false,
       currSent: null, //当前句子的时间
       isRecord: false,
+      isFull: false,
     };
   },
   computed: {
@@ -456,6 +471,26 @@ export default {
   },
   //方法集合
   methods: {
+    //语音全屏
+    fullScreen() {
+      this.isFull = true;
+      // var element = document.documentElement;
+      // if (element.requestFullscreen) {
+      //   element.requestFullscreen();
+      // } else if (element.mozRequestFullScreen) {
+      //   // 兼容火狐
+      //   element.mozRequestFullScreen();
+      // } else if (element.webkitRequestFullscreen) {
+      //   // 兼容谷歌
+      //   element.webkitRequestFullscreen();
+      // } else if (element.msRequestFullscreen) {
+      //   // 兼容IE
+      //   element.msRequestFullscreen();
+      // }
+    },
+    exitFullscreen() {
+      this.isFull = false;
+    },
     getWavblob(wavblob) {
       this.wavblob = wavblob;
     },
@@ -848,8 +883,10 @@ export default {
     }
   }
   .Soundrecord-content {
-    padding: 0px 0px 8px 68px;
-
+    padding: 0px 10px 8px 68px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
     &-inner {
       display: flex;
       justify-content: flex-start;
@@ -869,6 +906,20 @@ export default {
         align-items: center;
       }
     }
+    .full-screen-icon {
+      width: 16px;
+      height: 16px;
+      background: url("../../../../assets/NPC/full-screen-red.png") no-repeat
+        left top;
+      background-size: 100% 100%;
+      cursor: pointer;
+    }
+  }
+  .voice-full-screen {
+    position: fixed;
+    top: 0;
+    left: 0;
+    z-index: 9999;
   }
 }
 </style>

+ 476 - 0
src/components/Adult/preview/Soundrecorddiff.vue

@@ -0,0 +1,476 @@
+<!--  -->
+<template>
+  <div class="NNPE-Book-record">
+    <div :class="['record-main', microphoneStatus ? 'active' : '']">
+      <div class="record-main-inner">
+        <div class="record" @click="microphone" />
+        <span v-if="microphoneStatus" class="record-time">{{
+          handleDateTime(recordtime)
+        }}</span>
+      </div>
+    </div>
+    <div
+      :class="['hasRecord', bgIndex == 1 ? 'hasRecord-white' : '']"
+      v-if="!microphoneStatus && recordList.length > 0"
+    >
+      <div
+        :class="[bgIndex == 1 ? 'playBack-white' : 'playBack', hasMicro]"
+        @click="
+          playmicrophone(
+            selectIndex || selectIndex == 0
+              ? recordList[selectIndex].toltime
+              : ''
+          )
+        "
+      />
+      <span class="record-time"
+        >{{ isPlaying ? "-" : "" }}{{ handleDateTime(recordtime) }}</span
+      >
+      <el-select
+        v-model="selectIndex"
+        placeholder="无录音"
+        @change="handleChangeRecord"
+      >
+        <el-option
+          v-for="(item, index) in recordList"
+          :key="item.id"
+          :label="item.name"
+          :value="index"
+        />
+      </el-select>
+      <a class="record-delete" @click="handleDelete" />
+    </div>
+  </div>
+</template>
+
+<script>
+import Recorder from "js-audio-recorder"; // 录音插件
+export default {
+  components: {},
+  props: ["wavData", "type", "fileName", "selectData", "bgIndex"],
+  data() {
+    return {
+      recorder: new Recorder({
+        sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
+        sampleRate: 16000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
+        numChannels: 1, // 声道,支持 1 或 2, 默认是1
+      }),
+      microphoneStatus: false,
+      hasMicro: "", // 录音后的样式class
+      wavblob: null,
+      audio: new window.Audio(),
+      recordList: [], // 录音文件数组
+      recordtime: 0, // 录音时长
+      timer: null, // 计时器
+      recordFile: 1, // 录音文件名
+      selectIndex: null, // 选中的录音索引
+      oldIndex: null, // 存储播放录音索引
+      playtime: 0, // 播放时间
+      isPlaying: false,
+    };
+  },
+  computed: {},
+  watch: {},
+  // 生命周期 - 创建完成(可以访问当前this实例)
+  created() {
+    this.handleActive();
+    let that = this;
+    window.stopAudioSound = function () {
+      if (that.audio) {
+        that.audio.pause();
+      }
+    };
+  },
+  // 生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {
+    let _this = this;
+    _this.audio.addEventListener("play", function () {
+      _this.changeStatus("active");
+      _this.isPlaying = true;
+    });
+    _this.audio.addEventListener("pause", function () {
+      _this.changeStatus("normal");
+    });
+    _this.audio.addEventListener("ended", function () {
+      _this.changeStatus("normal");
+      _this.isPlaying = false;
+    });
+  },
+  beforeCreate() {}, // 生命周期 - 创建之前
+  beforeMount() {}, // 生命周期 - 挂载之前
+  beforeUpdate() {}, // 生命周期 - 更新之前
+  updated() {}, // 生命周期 - 更新之后
+  beforeDestroy() {}, // 生命周期 - 销毁之前
+  destroyed() {}, // 生命周期 - 销毁完成
+  activated() {},
+  // 方法集合
+  methods: {
+    // 开始录音
+    microphone() {
+      let _this = this;
+      if (!this.microphoneStatus) {
+        _this.$emit("getWavblob", null);
+        this.$emit("getSelectData", { type: "" });
+        // 开始录音
+        this.recorder.start();
+        this.microphoneStatus = true;
+        this.recordtime = 0;
+        this.isPlaying = false;
+        clearInterval(_this.timer);
+        _this.timer = setInterval(() => {
+          _this.recordtime++;
+        }, 1000);
+        this.$emit("handleParentPlay");
+        let obj = {
+          name: _this.fileName
+            ? _this.fileName + _this.recordFile
+            : "新录音" + _this.recordFile,
+          id: _this.recordFile + Math.round(Math.random() * 10),
+        };
+        if (this.selectData) obj.selectData = this.selectData;
+        _this.recordList.push(obj);
+        _this.recordFile++;
+        _this.selectIndex = _this.recordList.length - 1;
+      } else {
+        this.hasMicro = "normal";
+        this.recorder.stop();
+        clearInterval(_this.timer);
+        let toltime = this.recorder.duration; // 录音总时长
+        let fileSize = this.recorder.fileSize; // 录音总大小
+        // 录音结束,获取取录音数据
+        let PCMBlob = this.recorder.getPCMBlob(); // 获取 PCM 数据
+        let wav = this.recorder.getWAVBlob(); // 获取 WAV 数据
+        // this.wavblob = wav;
+        this.microphoneStatus = false;
+        let reader = new window.FileReader();
+        reader.readAsDataURL(wav);
+        reader.onloadend = () => {
+          _this.recordList[_this.selectIndex].wavData = reader.result;
+          _this.recordList[_this.selectIndex].toltime = Math.floor(toltime);
+          _this.recordList[_this.selectIndex].fileSize = fileSize;
+          //   if (
+          //     (_this.type && _this.type == "normal") ||
+          //     (_this.type && _this.type == "mini")
+          //   ) {
+          _this.wavblob = _this.recordList[_this.selectIndex].wavData;
+          _this.$emit("getWavblob", _this.wavblob);
+          if (this.recordList[this.selectIndex].selectData)
+            this.$emit(
+              "getSelectData",
+              this.recordList[this.selectIndex].selectData
+            );
+          //   }
+        };
+      }
+      _this.$emit(
+        "getRerordStatus",
+        !_this.microphoneStatus && _this.recordList.length > 0
+      );
+    },
+    playmicrophone(totalTimes) {
+      this.isPlaying = true;
+      if (this.selectIndex || this.selectIndex == 0) {
+        let totalTime = totalTimes;
+        let _this = this;
+        if (!this.audio.paused) {
+          this.audio.pause();
+          clearInterval(_this.timer);
+        } else if (this.audio.paused && _this.oldIndex == _this.selectIndex) {
+          _this.audio.play();
+          if (_this.recordtime == 0) {
+            _this.recordtime = totalTimes;
+            _this.playtime = 0;
+          }
+          _this.timer = setInterval(() => {
+            if (_this.playtime < totalTime) {
+              _this.playtime++;
+              _this.recordtime = totalTime - _this.playtime;
+            } else {
+              clearInterval(_this.timer);
+            }
+          }, 1000);
+        } else {
+          _this.audio.pause();
+          _this.audio.load();
+          _this.audio.src = _this.wavblob;
+          _this.oldIndex = _this.selectIndex;
+          _this.audio.play();
+          _this.playtime = 0;
+          _this.recordtime = totalTime;
+          clearInterval(_this.timer);
+          _this.timer = setInterval(() => {
+            if (_this.playtime < totalTime) {
+              _this.playtime++;
+              _this.recordtime = totalTime - _this.playtime;
+            } else {
+              clearInterval(_this.timer);
+            }
+          }, 1000);
+        }
+      }
+    },
+    // 高亮初始值
+    handleActive() {
+      if (this.wavData) {
+        // this.hasMicro = "normal";
+      } else {
+        this.hasMicro = "";
+      }
+    },
+    changeStatus(status) {
+      this.hasMicro = status;
+    },
+    // 格式化录音时长
+    handleDateTime(time) {
+      if (parseInt(time / 60) < 10) {
+        time =
+          ("0" + parseInt(time / 60)).substring(
+            ("0" + parseInt(time / 60)).length - 2
+          ) +
+          ":" +
+          ("0" + (time % 60)).substring(("0" + (time % 60)).length - 2);
+      } else {
+        time =
+          parseInt(time / 60) +
+          ":" +
+          ("0" + (time % 60)).substring(("0" + (time % 60)).length - 2);
+      }
+      return time;
+    },
+    handleChangeRecord(index) {
+      this.recordtime = this.recordList[index].toltime;
+      this.wavblob = this.recordList[index].wavData;
+      this.hasMicro = "normal";
+      clearInterval(this.timer);
+      this.audio.pause();
+      this.oldIndex = null;
+      this.$emit("getWavblob", this.wavblob);
+      if (this.recordList[index].selectData)
+        this.$emit("getSelectData", this.recordList[index].selectData);
+      this.$emit("sentPause", false);
+    },
+    handleDelete() {
+      if (this.selectIndex || this.selectIndex == 0) {
+        this.recordList.splice(this.selectIndex, 1);
+        this.selectIndex =
+          this.recordList.length > 0 ? this.recordList.length - 1 : null;
+        this.hasMicro = this.recordList.length > 0 ? "normal" : "";
+        this.recordtime =
+          this.recordList.length > 0
+            ? this.recordList[this.selectIndex].toltime
+            : 0;
+        this.audio.pause();
+        this.audio = new window.Audio();
+        this.wavblob =
+          this.recordList.length > 0
+            ? this.recordList[this.selectIndex].wavData
+            : null;
+        this.oldIndex = null;
+        this.isPlaying = false;
+        clearInterval(this.timer);
+      }
+    },
+  }, // 如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+.NNPE-Book-record {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  // max-width: 292px;
+  height: 32px;
+  // border: 1px solid rgba(0, 0, 0, 0.1);
+  // border-radius: 8px;
+  .playBack {
+    width: 24px;
+    height: 24px;
+    margin-left: 8px;
+    background: url("../../../assets/icon/play-24-normal-Black.png") center
+      no-repeat;
+    background-size: 100%;
+    cursor: pointer;
+    &.normal {
+      background: url("../../../assets/icon/play-24-normal-Black.png") center
+        no-repeat;
+      background-size: 100%;
+    }
+    &.active {
+      background: url("../../../assets/icon/pause-24-normal-Black.png") center
+        no-repeat;
+      background-size: 100%;
+    }
+  }
+  .playBack-white {
+    width: 24px;
+    height: 24px;
+    margin-left: 8px;
+    background: url("../../../assets/icon/play-24-normal-white.png") center
+      no-repeat;
+    background-size: 100%;
+    cursor: pointer;
+    &.normal {
+      background: url("../../../assets/icon/play-24-normal-white.png") center
+        no-repeat;
+      background-size: 100%;
+    }
+    &.active {
+      background: url("../../../assets/icon/pause-24-normal-white.png") center
+        no-repeat;
+      background-size: 100%;
+    }
+    .record-time {
+      color: #fff;
+    }
+  }
+  .line {
+    width: 1px;
+    height: 16px;
+    background: rgba(0, 0, 0, 0.85);
+    opacity: 0.2;
+    margin-left: 8px;
+  }
+  .record-main {
+    width: 162px;
+    height: 136px;
+    box-sizing: border-box;
+    padding: 40px 8px 40px 40px;
+    &.active {
+      background: url("../../../assets/NPC/vocie-gif.png") no-repeat left top;
+      background-size: 100% 100%;
+    }
+    &-inner {
+      padding: 16px 16px;
+      box-sizing: border-box;
+      width: fit-content;
+      height: 56px;
+      border-radius: 40px;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      box-sizing: border-box;
+      background: #de4444;
+      border: 1px solid rgba(0, 0, 0, 0.1);
+    }
+  }
+
+  .record {
+    width: 24px;
+    height: 24px;
+    background: url("../../../assets/NPC/voice-24.png") center no-repeat;
+    background-size: 100%;
+    cursor: pointer;
+  }
+  .record-time {
+    color: #fff;
+    font-size: 16px;
+    line-height: 150%;
+    margin-left: 8px;
+    font-family: "robot";
+    font-weight: bold;
+    font-size: 16px;
+    line-height: 24px;
+    margin-left: 16px;
+  }
+  .hasRecord {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    height: 56px;
+    padding: 16px 0 16px 16px;
+    border-radius: 40px 0 0 40px;
+    border: 1px solid rgba(0, 0, 0, 0.1);
+    border-right: 0px solid rgba(0, 0, 0, 0.1);
+    box-sizing: border-box;
+
+    .record-time {
+      width: 46px;
+      color: #000000;
+      text-align: center;
+    }
+
+    .el-select {
+      margin-left: 16px;
+    }
+    .record-delete {
+      width: 24px;
+      height: 24px;
+      margin-left: 16px;
+      background: url("../../../assets/NPC/del-24.png") center no-repeat;
+      background-size: 100%;
+      display: block;
+    }
+    &-white {
+      background: rgba(255, 255, 255, 0.1);
+      border: 1px solid rgba(0, 0, 0, 0.1);
+      border-right: 0;
+      .record-time {
+        color: #fff;
+      }
+    }
+  }
+}
+</style>
+<style lang="scss">
+.NNPE-Book-record {
+  .hasRecord {
+    .el-select {
+      flex: 1;
+      height: 24px;
+      &.proSelect {
+        width: 78px;
+      }
+      .el-input__inner {
+        width: 115px;
+        box-sizing: border-box;
+        height: 24px;
+        line-height: 22px;
+        border: 0px solid rgba(0, 0, 0, 0.1);
+        box-sizing: border-box;
+        border-radius: 4px;
+        padding: 0px 11px;
+        font-size: 14px;
+        color: rgba(0, 0, 0, 0.85);
+      }
+      .el-input {
+        .el-select__caret {
+          color: #000;
+          display: flex;
+          justify-content: center;
+          align-items: center;
+        }
+      }
+      .el-input__icon {
+        width: 16px;
+      }
+      .el-input__suffix {
+        right: 3px;
+      }
+    }
+    &-white {
+      .el-select {
+        .el-input__inner {
+          background: rgba(255, 255, 255, 0.1);
+          border-radius: 4px;
+          color: #fff;
+        }
+        .el-input {
+          .el-select__caret {
+            color: #000;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+          }
+        }
+        .el-input__icon {
+          width: 16px;
+        }
+        .el-input__suffix {
+          right: 3px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 998 - 0
src/components/Adult/preview/Voicefullscreen.vue

@@ -0,0 +1,998 @@
+<!--  -->
+<template>
+  <div :class="['voicefull', bgIndex == 0 ? 'bg1' : 'bg2']" v-if="sentList">
+    <div class="voicefull-top">
+      <div :class="['select-bg', bgIndex == 1 ? 'select-bg-blue' : '']">
+        <div :class="['bg-white-box', bgIndex == 0 ? 'active' : '']">
+          <span
+            :class="['bg-white', bgIndex == 0 ? 'active' : '']"
+            @click="changeBg(0)"
+          ></span>
+        </div>
+        <div :class="['bg-green-box', bgIndex == 1 ? 'active' : '']">
+          <span
+            :class="['bg-green', bgIndex == 1 ? 'active' : '']"
+            @click="changeBg(1)"
+          ></span>
+        </div>
+      </div>
+      <div class="top-middle">
+        <div :class="['audio-box', bgIndex == 1 ? 'audio-box-green' : '']">
+          <AudioLineSentence
+            :key="'sent' + curSentIndex"
+            :mp3="mp3"
+            :getCurTime="getCurTime"
+            ref="audioLineSent"
+            :audioId="'artPraAudioId' + curSentIndex"
+            :stopAudio="stopAudio"
+            :width="120"
+            :hideSlider="false"
+            :bg="bg"
+            :ed="ed"
+            :maxTime="maxTime"
+            :bgIndex="bgIndex"
+            :isRepeat="isRepeat"
+          />
+        </div>
+        <div
+          :class="['op-btn', bgIndex == 1 ? 'op-btn-green' : '']"
+          @click="changeStatus('isRepeat')"
+        >
+          <span
+            :class="[
+              'repeat-icon',
+              !isRepeat ? 'disabled' : '',
+              isRepeat && bgIndex == 1 ? 'repeat-icon-yellow' : '',
+            ]"
+          ></span>
+        </div>
+        <div
+          :class="['op-btn', bgIndex == 1 ? 'op-btn-green' : '']"
+          @click="changeStatus('isShowPY')"
+        >
+          <span
+            :class="[
+              'pinyin-icon',
+              !isShowPY ? 'disabled' : '',
+              isShowPY && bgIndex == 1 ? 'pinyin-icon-yellow' : '',
+            ]"
+          ></span>
+        </div>
+        <div
+          :class="['op-btn', bgIndex == 1 ? 'op-btn-green' : '']"
+          @click="changeStatus('isShowEN')"
+        >
+          <span
+            :class="[
+              'en-icon',
+              !isShowEN ? 'disabled' : '',
+              isShowEN && bgIndex == 1 ? 'en-icon-yellow' : '',
+            ]"
+          ></span>
+        </div>
+        <div
+          :class="['op-btn', bgIndex == 1 ? 'op-btn-green' : '']"
+          @click="addColl('isColl')"
+        >
+          <span
+            :class="[
+              'coll-icon',
+              !isColl ? 'disabled' : '',
+              isColl && bgIndex == 1 ? 'coll-icon-yellow' : '',
+            ]"
+          ></span>
+        </div>
+      </div>
+      <div
+        :class="['op-btn', bgIndex == 1 ? 'op-btn-green' : '']"
+        @click="exitFullScreen"
+      >
+        <span
+          :class="['close-icon', bgIndex == 1 ? 'close-icon-yellow' : '']"
+        ></span>
+      </div>
+    </div>
+    <div
+      class="voicefull-content"
+      v-if="item"
+      @mousemove="showPrevNext(true)"
+      @mouseleave="showPrevNext(false)"
+    >
+      <div
+        :class="[
+          'vc-left vc-left-grey',
+          isShow && bgIndex == 0 ? 'vc-left-black' : '',
+          isShow && bgIndex == 1 ? 'vc-left-white' : '',
+        ]"
+        @click="prevSentence"
+      ></div>
+      <div class="vc-main">
+        <div class="NNPE-words-box">
+          <div
+            class="NNPE-words"
+            v-for="(pItem, pIndex) in item.sentArr"
+            :key="'wordsList' + pIndex"
+            :class="[pItem.wordIndex == 0 ? 'textLeft' : 'textCenter']"
+          >
+            <template v-if="!pItem.width">
+              <template v-if="pItem.isShow">
+                <template
+                  v-if="
+                    item.sentArr[pIndex + 1] &&
+                    item.sentArr[pIndex + 1].chs &&
+                    chsFhList.indexOf(item.sentArr[pIndex + 1].chs) > -1
+                  "
+                >
+                  <span class="NNPE-words-box">
+                    <template v-if="curQue.pyPosition == 'top'">
+                      <span
+                        v-if="isShowPY"
+                        class="NNPE-pinyin"
+                        :class="[
+                          pItem.className ? pItem.className : '',
+                          noFont.indexOf(item.pinyin) > -1 ? 'noFont' : '',
+                          bgIndex == 1 ? 'font-white' : '',
+                        ]"
+                        >{{ pItem.pinyin }}</span
+                      >
+                    </template>
+                    <span
+                      class="NNPE-chs"
+                      :class="[pItem.padding && isShowPY ? 'padding' : '']"
+                    >
+                      <template>
+                        <span
+                          v-for="(wItem, wIndex) in pItem.leg"
+                          :key="'ci' + wIndex + pIndex"
+                          :class="[
+                            isPlaying &&
+                            pItem.timeList &&
+                            pItem.timeList[wIndex] &&
+                            curTime >= pItem.timeList[wIndex].wordBg &&
+                            curQue.wordTime &&
+                            curQue.wordTime[curSentIndex] &&
+                            curTime <= curQue.wordTime[curSentIndex].ed
+                              ? 'active'
+                              : '',
+                            bgIndex == 1 ? 'font-white' : '',
+                          ]"
+                          >{{ pItem.chs[wIndex] }}</span
+                        >
+                      </template>
+                    </span>
+                    <template v-if="curQue.pyPosition == 'bottom'">
+                      <span
+                        v-if="isShowPY"
+                        class="NNPE-pinyin"
+                        :class="[
+                          pItem.className ? pItem.className : '',
+                          noFont.indexOf(item.pinyin) > -1 ? 'noFont' : '',
+                          bgIndex == 1 ? 'font-white' : '',
+                        ]"
+                        >{{ pItem.pinyin }}</span
+                      >
+                    </template>
+                  </span>
+                  <span class="NNPE-words-box">
+                    <template v-if="curQue.pyPosition == 'top'">
+                      <span
+                        v-if="isShowPY"
+                        :class="[
+                          'NNPE-pinyin',
+                          noFont.indexOf(item.sentArr[pIndex + 1].pinyin) > -1
+                            ? 'noFont'
+                            : '',
+                          bgIndex == 1 ? 'font-white' : '',
+                        ]"
+                        style="text-align: left"
+                        >{{ item.sentArr[pIndex + 1].pinyin }}</span
+                      >
+                    </template>
+                    <span class="NNPE-chs" style="text-align: left">
+                      <span
+                        :class="[
+                          isPlaying &&
+                          pItem.timeList[pItem.leg - 1] &&
+                          curTime >= pItem.timeList[pItem.leg - 1].wordBg &&
+                          curQue.wordTime &&
+                          curQue.wordTime[curSentIndex] &&
+                          curTime <= curQue.wordTime[curSentIndex].ed
+                            ? 'active'
+                            : '',
+                          bgIndex == 1 ? 'font-white' : '',
+                        ]"
+                      >
+                        {{ item.sentArr[pIndex + 1].chs }}</span
+                      >
+                    </span>
+                    <template v-if="curQue.pyPosition == 'bottom'">
+                      <span
+                        v-if="isShowPY"
+                        :class="[
+                          'NNPE-pinyin',
+                          noFont.indexOf(item.sentArr[pIndex + 1].pinyin) > -1
+                            ? 'noFont'
+                            : '',
+                          bgIndex == 1 ? 'font-white' : '',
+                        ]"
+                        style="text-align: left"
+                        >{{ item.sentArr[pIndex + 1].pinyin }}</span
+                      >
+                    </template>
+                  </span>
+                </template>
+                <template v-else>
+                  <template v-if="curQue.pyPosition == 'top'">
+                    <template v-if="NumberList.indexOf(pItem.pinyin) < 0">
+                      <span
+                        v-if="isShowPY"
+                        class="NNPE-pinyin"
+                        :class="[
+                          pItem.padding ? 'padding' : '',
+                          pItem.className ? pItem.className : '',
+                          noFont.indexOf(item.pinyin) > -1 ? 'noFont' : '',
+                          bgIndex == 1 ? 'font-white' : '',
+                        ]"
+                        >{{ pItem.pinyin }}</span
+                      >
+                    </template>
+                  </template>
+                  <span
+                    v-if="pItem.chs != '#'"
+                    class="NNPE-chs"
+                    :class="[pItem.padding && isShowPY ? 'padding' : '']"
+                  >
+                    <template>
+                      <span
+                        v-for="(wItem, wIndex) in pItem.leg"
+                        :key="'ci' + wIndex + pIndex + curSentIndex"
+                        :class="[
+                          isPlaying &&
+                          pItem.timeList &&
+                          pItem.timeList[wIndex] &&
+                          curTime >= pItem.timeList[wIndex].wordBg &&
+                          curQue.wordTime &&
+                          curQue.wordTime[curSentIndex] &&
+                          curTime <= curQue.wordTime[curSentIndex].ed
+                            ? 'active'
+                            : '',
+                          bgIndex == 1 ? 'font-white' : '',
+                        ]"
+                        >{{ pItem.chs[wIndex] }}</span
+                      >
+                    </template>
+                  </span>
+                  <template v-if="curQue.pyPosition == 'bottom'">
+                    <template v-if="NumberList.indexOf(pItem.pinyin) < 0">
+                      <span
+                        v-if="isShowPY"
+                        class="NNPE-pinyin"
+                        :class="[
+                          pItem.padding ? 'padding' : '',
+                          pItem.className ? pItem.className : '',
+                          bgIndex == 1 ? 'font-white' : '',
+                        ]"
+                        >{{ pItem.pinyin }}</span
+                      >
+                    </template>
+                  </template>
+                </template>
+              </template>
+            </template>
+            <template v-else>
+              <span
+                :style="{
+                  height: pItem.height + 'px',
+                  width: pItem.width + 'px',
+                }"
+              ></span>
+            </template>
+          </div>
+        </div>
+        <div style="clear: both; overflow: hidden"></div>
+        <div
+          v-if="item.enwords && isShowEN"
+          :class="['enwords', bgIndex == 1 ? 'enwords-green' : '']"
+        >
+          {{ item.enwords }}
+        </div>
+      </div>
+      <div
+        :class="[
+          'vc-left vc-right-grey',
+          isShow && bgIndex == 0 ? 'vc-right-black' : '',
+          isShow && bgIndex == 1 ? 'vc-right-white' : '',
+        ]"
+        @click="nextSentence"
+      ></div>
+    </div>
+    <div class="voicefull-bottom">
+      <div class="bottom-left">
+        <Soundrecorddiff
+          @handleWav="handleWav"
+          @getWavblob="getWavblob"
+          @handleParentPlay="handleParentPlay"
+          @sentPause="sentPause"
+          @getRerordStatus="getRerordStatus"
+          :bgIndex="bgIndex"
+        />
+        <div
+          :class="['compare-box', bgIndex == 1 ? 'compare-box-white' : '']"
+          v-if="isShowCompare"
+        >
+          <Audio-compare
+            :bgIndex="bgIndex"
+            type="full"
+            :themeColor="themeColor"
+            :index="curSentIndex"
+            :curSentIndex="curSentIndex"
+            :url="curQue.mp3_list[0].id"
+            :bg="bg"
+            :ed="ed"
+            :wavblob="wavblob"
+            :getCurTime="getCurTime"
+            :sentPause="sentPause"
+            :isRecord="isRecord"
+            :handleChangeStopAudio="handleChangeStopAudio"
+          />
+        </div>
+      </div>
+      <div
+        :class="[
+          'page-count',
+          bgIndex == 0 ? 'page-count-white' : 'page-count-green',
+        ]"
+      >
+        {{ curSentIndex + 1 }}/{{ sentList.length }}
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import AudioLineSentence from "./AudioLineSentence.vue";
+import Soundrecorddiff from "./Soundrecorddiff.vue";
+import AudioCompare from "./AudioCompare.vue";
+export default {
+  components: {
+    AudioLineSentence,
+    Soundrecorddiff,
+    AudioCompare,
+  },
+  props: [
+    "sentList",
+    "sentIndex",
+    "mp3",
+    "wordTimeList",
+    "curQue",
+    "noFont",
+    "themeColor",
+  ],
+  data() {
+    return {
+      bgIndex: 0,
+      maxTime: 0,
+      item: null,
+      bg: 0,
+      ed: 0,
+      isShowPY: true,
+      isRepeat: false,
+      isShowEN: true,
+      isColl: false,
+      NumberList: [
+        "①",
+        "②",
+        "③",
+        "④",
+        "⑤",
+        "⑥",
+        "⑦",
+        "⑧",
+        "⑨",
+        "⑩",
+        "⑪",
+        "⑫",
+        "⑬",
+        "⑭",
+        "⑮",
+        "⑯",
+        "⑰",
+        "⑱",
+        "⑲",
+        "⑳",
+      ],
+      chsFhList: [",", "。", "“", ":", "》", "《", "?", "!", ";"],
+      enFhList: [",", ".", ";", "?", "!", ":", ">", "<"],
+      curTime: 0,
+      wavblob: null,
+      stopAudio: false,
+      isRecord: false,
+      isShowCompare: false,
+      isShow: false,
+      curSentIndex: 0,
+    };
+  },
+  computed: {
+    isPlaying: function () {
+      let playing = false;
+      if (this.$refs.audioLineSent) {
+        playing = this.$refs.audioLineSent.audio.isPlaying;
+      }
+      return playing;
+    },
+  },
+  watch: {
+    sentIndex: {
+      handler: function (newVal, oldVal) {
+        this.curSentIndex = newVal;
+        this.getSentence();
+      },
+      deep: true,
+    },
+  },
+  //方法集合
+  methods: {
+    //添加收藏
+    addColl() {
+      let Bookdetail = sessionStorage.getItem("Bookdetail");
+      if (Bookdetail) {
+        Bookdetail = JSON.parse(Bookdetail);
+      }
+      let MethodName = "order-collection_manager-AddMyCollection";
+      let text = "";
+      this.item.sentArr.forEach((item) => {
+        if (item.chs != "#") {
+          text += item.chs;
+        }
+      });
+      let sentence_json = {
+        item: JSON.stringify(this.item),
+        bg: this.bg,
+        ed: this.ed,
+      };
+      let data = {
+        goods_id: this.currentTreeID,
+        goods_type: 501,
+        goods_name: Bookdetail.name,
+        goods_person_name_desc: Bookdetail.description
+          ? Bookdetail.description
+          : "",
+        goods_picture_id: Bookdetail.picture_id ? Bookdetail.picture_id : "",
+        goods_price: Bookdetail.price,
+        sentence: {
+          sentence_text: text,
+          sentence_json: JSON.stringify(sentence_json),
+        },
+      };
+      console.log(text);
+      LearnWebSI(MethodName, data).then((res) => {
+        this.isColl = true;
+        this.$message.success("收藏成功!");
+      });
+    },
+    showPrevNext(bool) {
+      this.isShow = bool;
+    },
+    prevSentence() {
+      if (this.curSentIndex == 0) {
+        this.$message.warning("已经是第一个句子了");
+        return;
+      }
+      this.curSentIndex = this.curSentIndex - 1;
+      this.getSentence();
+    },
+    nextSentence() {
+      if (this.curSentIndex == this.sentList.length - 1) {
+        this.$message.warning("已经是最后一个句子了");
+        return;
+      }
+      this.curSentIndex = this.curSentIndex + 1;
+      this.getSentence();
+    },
+    changeStatus(key) {
+      this[key] = !this[key];
+    },
+    getRerordStatus(bool) {
+      this.isShowCompare = bool;
+    },
+    getWavblob(wavblob) {
+      this.wavblob = wavblob;
+    },
+    sentPause(isRecord) {
+      this.isRecord = isRecord;
+    },
+    getCurTime(curTime) {
+      let _this = this;
+      if (_this.isRepeat) {
+        let time = curTime * 1000;
+        if (time > _this.ed || time < _this.bg) {
+          _this.curTime = _this.bg;
+          this.$refs.audioLineSent.onTimeupdateTime(_this.bg / 1000);
+        } else {
+          _this.curTime = curTime * 1000;
+        }
+      } else {
+        _this.curTime = curTime * 1000;
+      }
+    },
+    changeBg(bgIndex) {
+      this.bgIndex = bgIndex;
+    },
+    getSentence() {
+      let _this = this;
+      _this.item = _this.sentList[_this.curSentIndex];
+      _this.bg = _this.curQue.wordTime[_this.curSentIndex].bg;
+      _this.ed = _this.curQue.wordTime[_this.curSentIndex].ed;
+      let maxTime = (_this.ed - _this.bg) / 1000;
+      if (maxTime < 1) {
+        _this.maxTime = 1;
+      } else {
+        _this.maxTime = maxTime;
+      }
+      console.log(_this.sentList);
+    },
+    exitFullScreen() {
+      this.$emit("exitFullscreen");
+    },
+    handleWav(data) {},
+    // 录音时暂停音频播放
+    handleParentPlay() {
+      this.stopAudio = true;
+    },
+    // 音频播放时改变布尔值
+    handleChangeStopAudio() {
+      this.stopAudio = false;
+    },
+  },
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {
+    this.curSentIndex = this.sentIndex;
+    console.log(this.curSentIndex);
+    this.getSentence();
+  },
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+.voicefull {
+  width: 100vh;
+  height: 100vh;
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+  &.bg1 {
+    background: #fff;
+  }
+  &.bg2 {
+    background: linear-gradient(180deg, #274533 0%, #385f45 100%);
+  }
+  &-top {
+    height: 136px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 0 40px;
+    .select-bg {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      width: 96px;
+      height: 56px;
+      border: 1px solid rgba(0, 0, 0, 0.1);
+      border-radius: 40px;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      box-sizing: border-box;
+      &.select-bg-blue {
+        background: rgba(255, 255, 255, 0.1);
+        border: 1px solid rgba(0, 0, 0, 0.1);
+      }
+      > div {
+        width: 36px;
+        height: 36px;
+        border-radius: 100%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        &.bg-white-box {
+          background: 0 0;
+          margin-right: 4px;
+          &.active {
+            background: #de4444;
+          }
+        }
+        &.bg-green-box {
+          background: #fff;
+          &.active {
+            background: #ffc600;
+          }
+        }
+
+        > span {
+          width: 24px;
+          height: 24px;
+          border-radius: 100%;
+          box-sizing: border-box;
+          cursor: pointer;
+          &.bg-white {
+            background: #fff;
+          }
+          &.bg-green {
+            background: linear-gradient(180deg, #274533 0%, #385f45 100%);
+          }
+        }
+      }
+    }
+    .top-middle {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      .audio-box {
+        padding: 0 16px;
+        height: 56px;
+        background: #ffffff;
+        border: 1px solid rgba(0, 0, 0, 0.1);
+        border-radius: 40px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        &-green {
+          background: rgba(255, 255, 255, 0.1);
+          border: 1px solid rgba(0, 0, 0, 0.1);
+        }
+      }
+    }
+    .op-btn {
+      width: 56px;
+      height: 56px;
+      border-radius: 100%;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+
+      cursor: pointer;
+      margin-left: 32px;
+      background: #ffffff;
+      border: 1px solid rgba(0, 0, 0, 0.1);
+      box-sizing: border-box;
+      &-green {
+        background: rgba(255, 255, 255, 0.1);
+        border: 1px solid rgba(0, 0, 0, 0.1);
+      }
+      &.close-btn {
+        background: #274533;
+        border: 1px solid rgba(0, 0, 0, 0.1);
+      }
+      > span {
+        width: 24px;
+        height: 24px;
+        &.close-icon {
+          background: url("../../../assets/icon/cross-24-normal-black.png")
+            no-repeat left top;
+          background-size: 100% 100%;
+          &-white {
+            background: url("../../../assets/icon/cross-24-normal-white.png")
+              no-repeat left top;
+            background-size: 100% 100%;
+          }
+        }
+      }
+    }
+  }
+  .repeat-icon {
+    background: url("../../../assets/icon/Repeat-24-normal-red.png") no-repeat
+      left top;
+    background-size: 100% 100%;
+    &.disabled {
+      background: url("../../../assets/icon/Repeat-24-disable-Black.png")
+        no-repeat left top;
+      background-size: 100% 100%;
+    }
+    &-yellow {
+      background: url("../../../assets/icon/Repeat-24-normal-yellow.png")
+        no-repeat left top;
+      background-size: 100% 100%;
+    }
+  }
+  .pinyin-icon {
+    background: url("../../../assets/icon/pinyin-24-normal-red.png") no-repeat
+      left top;
+    background-size: 100% 100%;
+    &.disabled {
+      background: url("../../../assets/icon/pinyin-24-disable-Black.png")
+        no-repeat left top;
+      background-size: 100% 100%;
+    }
+    &-yellow {
+      background: url("../../../assets/icon/pinyin-24-normal-yellow.png")
+        no-repeat left top;
+      background-size: 100% 100%;
+    }
+  }
+  .en-icon {
+    background: url("../../../assets/icon/EN-24-normal-Red.png") no-repeat left
+      top;
+    background-size: 100% 100%;
+    &.disabled {
+      background: url("../../../assets/icon/EN-24-disable-Black.png") no-repeat
+        left top;
+      background-size: 100% 100%;
+    }
+    &-yellow {
+      background: url("../../../assets/icon/EN-24-normal-yellow.png") no-repeat
+        left top;
+      background-size: 100% 100%;
+    }
+  }
+  .coll-icon {
+    background: url("../../../assets/icon/bookmarkfill-24-normal-red.png")
+      no-repeat left top;
+    background-size: 100% 100%;
+    &.disabled {
+      background: url("../../../assets/icon/bookmarkfill-24-disable-Black.png")
+        no-repeat left top;
+      background-size: 100% 100%;
+    }
+    &-yellow {
+      background: url("../../../assets/icon/bookmarkfill-24-normal-yellow.png")
+        no-repeat left top;
+      background-size: 100% 100%;
+    }
+  }
+
+  &-content {
+    flex: 1;
+    width: 100%;
+    box-sizing: border-box;
+    padding: 0 36px;
+    display: flex;
+    align-items: center;
+
+    .vc-left {
+      width: 64px;
+      height: 64px;
+      cursor: pointer;
+      &-grey {
+        background: url("../../../assets/NPC/left-grey.png") no-repeat left top;
+        background-size: 100% 100%;
+      }
+      &-black {
+        background: url("../../../assets/NPC/left-black.png") no-repeat left top;
+        background-size: 100% 100%;
+      }
+      &-white {
+        background: url("../../../assets/NPC/left-white.png") no-repeat left top;
+        background-size: 100% 100%;
+      }
+    }
+    .vc-right {
+      width: 64px;
+      height: 64px;
+      cursor: pointer;
+      &-grey {
+        background: url("../../../assets/NPC/right-grey.png") no-repeat left top;
+        background-size: 100% 100%;
+      }
+      &-black {
+        background: url("../../../assets/NPC/right-black.png") no-repeat left
+          top;
+        background-size: 100% 100%;
+      }
+      &-white {
+        background: url("../../../assets/NPC/right-white.png") no-repeat left
+          top;
+        background-size: 100% 100%;
+      }
+    }
+    .vc-main {
+      width: fit-content;
+      margin: 0 auto;
+      .enwords {
+        padding: 0 3px;
+        margin-top: 40px;
+        color: rgba(0, 0, 0, 0.45);
+        font-size: 24px;
+        line-height: 32px;
+        font-family: "robot";
+        &-green {
+          color: rgba(255, 255, 255, 0.65);
+        }
+      }
+    }
+    .NNPE-words {
+      float: left;
+      &-box {
+        float: left;
+        > span {
+          display: block;
+          &.NNPE-pinyin {
+            font-family: "GB-PINYINOK-B";
+            font-weight: normal;
+            font-size: 32px;
+            line-height: 40px;
+
+            height: 40px;
+            color: rgba(0, 0, 0, 0.85);
+
+            &.noFont {
+              font-family: initial;
+            }
+            &.textLeft {
+              text-align: left;
+            }
+            &.wordBlank {
+              color: rgba(0, 0, 0, 0.85);
+            }
+            &.font-white {
+              color: #fff;
+            }
+          }
+          &.NNPE-chs {
+            font-family: "FZJCGFKTK";
+            font-size: 48px;
+            line-height: 56px;
+            padding-bottom: 16px;
+            color: rgba(0, 0, 0, 0.85);
+
+            .active {
+              color: #de4444;
+            }
+            .font-white {
+              color: #fff;
+            }
+          }
+          // &.padding {
+          //   padding-right: 6px;
+          // }
+        }
+      }
+      &.textLeft {
+        text-align: left;
+      }
+      &.textCenter {
+        text-align: center;
+      }
+      > span {
+        display: block;
+        &.NNPE-pinyin {
+          font-family: "GB-PINYINOK-B";
+          font-weight: normal;
+          font-size: 32px;
+          line-height: 40px;
+          height: 40px;
+          color: rgba(0, 0, 0, 0.85);
+          &.noFont {
+            font-family: initial;
+          }
+          &.textLeft {
+            text-align: left;
+          }
+          &.wordBlank {
+            color: rgba(0, 0, 0, 0.85);
+          }
+          &.font-white {
+            color: #fff;
+          }
+        }
+        &.NNPE-chs {
+          font-family: "FZJCGFKTK";
+          font-size: 48px;
+          line-height: 56px;
+          padding-bottom: 16px;
+          color: rgba(0, 0, 0, 0.85);
+          .active {
+            color: #de4444;
+          }
+          .font-white {
+            color: #fff;
+          }
+        }
+        &.padding {
+          padding: 0 3px;
+        }
+      }
+    }
+  }
+  &-bottom {
+    height: 136px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding-right: 40px;
+    .bottom-left {
+      display: flex;
+      justify-content: flex-start;
+      align-items: center;
+      .compare-box {
+        height: 56px;
+        padding: 16px 16px;
+        box-sizing: border-box;
+        border: 1px solid rgba(0, 0, 0, 0.1);
+        border-radius: 0 40px 40px 0;
+        border-left: 0px solid rgba(0, 0, 0, 0.1);
+        &-white {
+          background: rgba(255, 255, 255, 0.1);
+          border: 1px solid rgba(0, 0, 0, 0.1);
+          border-left: 0;
+        }
+      }
+    }
+    .page-count {
+      padding: 8px;
+      font-size: 16px;
+      line-height: 24px;
+      font-family: "robot";
+      color: #000000;
+      min-width: 60px;
+      box-sizing: border-box;
+      border-radius: 8px;
+      background: #fff;
+      text-align: center;
+      &-green {
+        color: #ffffff;
+        background: rgba(255, 255, 255, 0.2);
+      }
+    }
+  }
+}
+</style>
+<style lang="scss">
+.NPC-Big-Book-preview-green {
+  .bg2 {
+    .repeat-icon {
+      background: url("../../../assets/icon/Repeat-24-normal-Green.png")
+        no-repeat left top;
+      background-size: 100% 100%;
+    }
+    .pinyin-icon {
+      background: url("../../../assets/icon/pinyin-24-normal-green.png")
+        no-repeat left top;
+      background-size: 100% 100%;
+    }
+    .en-icon {
+      background: url("../../../assets/icon/EN-24-normal-Green.png") no-repeat
+        left top;
+      background-size: 100% 100%;
+    }
+    .coll-icon {
+      background: url("../../../assets/icon/bookmarkfill-24-normal-green.png")
+        no-repeat left top;
+      background-size: 100% 100%;
+    }
+  }
+}
+.NPC-Big-Book-preview-brown {
+  .bg2 {
+    .repeat-icon {
+      background: url("../../../assets/icon/Repeat-24-normal-Brown.png")
+        no-repeat left top;
+      background-size: 100% 100%;
+    }
+    .pinyin-icon {
+      background: url("../../../assets/icon/pinyin-24-normal-brown.png")
+        no-repeat left top;
+      background-size: 100% 100%;
+    }
+    .en-icon {
+      background: url("../../../assets/icon/EN-24-normal-Brown.png") no-repeat
+        left top;
+      background-size: 100% 100%;
+    }
+    .coll-icon {
+      background: url("../../../assets/icon/bookmarkfill-24-normal-brown.png")
+        no-repeat left top;
+      background-size: 100% 100%;
+    }
+  }
+}
+</style>

+ 20 - 15
src/components/Adult/preview/components/AudioRed.vue

@@ -1,14 +1,14 @@
 <!--  -->
 <template>
   <div v-if="mp3" class="content-voices" @click="handlePlayVoice">
-    <img :src="voiceSrc">
+    <img :src="voiceSrc" :class="type == 'full' ? 'icon-big' : ''" />
   </div>
 </template>
 
 <script>
 export default {
   components: {},
-  props: ["seconds", "mp3", "wav", "themeColor", "isCompare"],
+  props: ["seconds", "mp3", "wav", "themeColor", "isCompare", "type"],
   data() {
     return {
       audio: new Audio(),
@@ -17,15 +17,15 @@ export default {
         ? this.themeColor == "green"
           ? require("../../../../assets/NPC/play-green.png")
           : this.themeColor == "brown"
-            ? require("../../../../assets/NPC/play-brown.png")
-            : require("../../../../assets/NPC/play-red.png")
+          ? require("../../../../assets/NPC/play-brown.png")
+          : require("../../../../assets/NPC/play-red.png")
         : require("../../../../assets/NPC/play-red.png"),
       voicePlaySrc: this.themeColor
         ? this.themeColor == "green"
           ? require("../../../../assets/NPC/icon-voice-play-green.png")
           : this.themeColor == "brown"
-            ? require("../../../../assets/NPC/icon-voice-play-brown.png")
-            : require("../../../../assets/NPC/icon-voice-play-red.png")
+          ? require("../../../../assets/NPC/icon-voice-play-brown.png")
+          : require("../../../../assets/NPC/icon-voice-play-red.png")
         : require("../../../../assets/NPC/icon-voice-play-red.png"),
     };
   },
@@ -33,25 +33,25 @@ export default {
     comparePauseSrc() {
       switch (this.themeColor) {
         case "green":
-          return require("../../../../assets/NPC/compare-pause-green.png");
+          return require("../../../../assets/NPC/compare-pause-green-24.png");
         case "brown":
-          return require("../../../../assets/NPC/compare-pause-brown.png");
+          return require("../../../../assets/NPC/compare-pause-brown-24.png");
         case "red":
-          return require("../../../../assets/NPC/compare-pause-red.png");
+          return require("../../../../assets/NPC/compare-pause-red-24.png");
         default:
-          return require("../../../../assets/NPC/compare-pause-red.png");
+          return require("../../../../assets/NPC/compare-pause-red-24.png");
       }
     },
     comparePlaySrc() {
       switch (this.themeColor) {
         case "green":
-          return require("../../../../assets/icon/pauseC-16-normal-Green.png");
+          return require("../../../../assets/icon/pauseC-24-normal-Green.png");
         case "brown":
-          return require("../../../../assets/icon/pauseC-16-normal-Brown.png");
+          return require("../../../../assets/icon/pauseC-24-normal-Brown.png");
         case "red":
-          return require("../../../../assets/icon/pauseC-16-normal-red.png");
+          return require("../../../../assets/icon/pauseC-24-normal-red.png");
         default:
-          return require("../../../../assets/icon/pauseC-16-normal-red.png");
+          return require("../../../../assets/icon/pauseC-24-normal-red.png");
       }
     },
   },
@@ -118,7 +118,7 @@ export default {
         this.audio.pause();
       }
     },
-  }
+  },
 };
 </script>
 <style lang='scss' scoped>
@@ -141,8 +141,13 @@ export default {
     }
   }
   img {
+    width: 16px;
     height: 16px;
     float: left;
   }
+  .icon-big {
+    width: 24px;
+    height: 24px;
+  }
 }
 </style>

+ 57 - 14
src/components/Adult/preview/components/Wordcard.vue

@@ -11,7 +11,9 @@
       <i class="el-icon-close" @click="changeWordCard(false)"></i>
     </div>
     <div class="bwc-top" v-if="word.detail">
-      <span v-if="word.detail.pinyin">{{ word.detail.pinyin.toLowerCase() }}</span>
+      <span v-if="word.detail.pinyin">{{
+        word.detail.pinyin.toLowerCase()
+      }}</span>
       <div style="margin-left: 4px" v-if="mp3Url">
         <Audio :mp3="mp3Url ? mp3Url : ''" :themeColor="themeColor" />
       </div>
@@ -98,19 +100,35 @@
     </template>
     <div class="bwc-more-intp" @click="viewIntp">查看更多</div>
     <div class="bwc-footer">
-      <button class="bwc-btn">
-        <img
-          :src="
-            themeColor
-              ? themeColor == 'green'
-                ? require('../../../../assets/icon/starline-16-normal-Green.png')
-                : themeColor == 'brown'
-                ? require('../../../../assets/icon/starline-16-normal-Brown.png')
+      <button class="bwc-btn" @click="addColl">
+        <template v-if="!collFlag">
+          <img
+            :src="
+              themeColor
+                ? themeColor == 'green'
+                  ? require('../../../../assets/icon/starline-16-normal-Green.png')
+                  : themeColor == 'brown'
+                  ? require('../../../../assets/icon/starline-16-normal-Brown.png')
+                  : require('../../../../assets/icon/starline-16-normal-red.png')
                 : require('../../../../assets/icon/starline-16-normal-red.png')
-              : require('../../../../assets/icon/starline-16-normal-red.png')
-          "
-          class="collect-icon"
-        />
+            "
+            class="collect-icon"
+          />
+        </template>
+        <template v-else>
+          <img
+            :src="
+              themeColor
+                ? themeColor == 'green'
+                  ? require('../../../../assets/icon/starline-16-normal-Green.png')
+                  : themeColor == 'brown'
+                  ? require('../../../../assets/icon/starline-16-normal-Brown.png')
+                  : require('../../../../assets/icon/starline-16-normal-red.png')
+                : require('../../../../assets/icon/starline-16-normal-red.png')
+            "
+            class="practice-icon"
+          />
+        </template>
         收藏
       </button>
       <button
@@ -158,7 +176,7 @@ import Audio from "./AudioRed.vue";
 import Strockplayredline from "./Strockplayredline.vue";
 import Practice from "./Practice.vue";
 import WordPhraseDetail from "./WordPhraseDetail.vue";
-import { getContentFile, getContent, getHZChineseInfo } from "@/api/ajax";
+import { getContentFile, LearnWebSI, getHZChineseInfo } from "@/api/ajax";
 import { isChn } from "@/utils/index";
 
 export default {
@@ -180,6 +198,7 @@ export default {
       dataDetail: null,
       defChsArr: [],
       defEnArr: [],
+      collFlag: false,
     };
   },
   computed: {},
@@ -196,6 +215,30 @@ export default {
   },
   //方法集合
   methods: {
+    addColl() {
+      let Bookdetail = sessionStorage.getItem("Bookdetail");
+      if (Bookdetail) {
+        Bookdetail = JSON.parse(Bookdetail);
+      }
+      let MethodName = "order-collection_manager-AddMyCollection";
+      let data = {
+        goods_id: this.currentTreeID,
+        goods_type: 501,
+        goods_name: Bookdetail.name,
+        goods_person_name_desc: Bookdetail.description
+          ? Bookdetail.description
+          : "",
+        goods_picture_id: Bookdetail.picture_id ? Bookdetail.picture_id : "",
+        goods_price: Bookdetail.price,
+        new_word: {
+          new_word: this.word.detail.new_word,
+        },
+      };
+      LearnWebSI(MethodName, data).then((res) => {
+        this.collFlag = true;
+        this.$message.success("收藏成功!");
+      });
+    },
     async writeWord(words, pinyin) {
       let _this = this;
       const MethodName = "tool-ChineseSCConvert";

+ 1 - 11
src/styles/index.scss

@@ -265,17 +265,7 @@ input:-ms-input-placeholder {
                 background: url("../assets/icon/play-16-normal-red.png") no-repeat left top;
                 background-size: 100% 100%;
             }
-            .el-slider__bar {
-                height: 2px;
-                background: #DE4444;
-            }
-            .el-slider__button {
-                background: #DE4444;
-                border: none;
-            }
-            .el-slider__button-wrapper {
-                width: 25px;
-            }
+            
         }
         &.Audio-tts {
             .audioLine {

+ 5 - 2
src/views/adultInput.vue

@@ -758,7 +758,6 @@ import Table from "@/components/Adult/inputModules/Table.vue";
 import PlayRecord from "@/components/Adult/inputModules/PlayRecord.vue";
 import UploadPdf from "@/components/Adult/inputModules/UploadPdf.vue";
 
-
 import Textdes from "@/components/Adult/inputModules/Textdes.vue";
 import Record from "@/components/Adult/inputModules/Record.vue";
 import Hanzi from "@/components/Adult/inputModules/Hanzi.vue";
@@ -1402,7 +1401,11 @@ export default {
       let resArr = [];
       list.forEach((item) => {
         if (item != "#" && this.NumberList.indexOf(item) < 0) {
-          resArr.push(item);
+          let obj = {
+            word: item,
+            word_bt: "",
+          };
+          resArr.push(obj);
         }
       });
       return resArr;

+ 63 - 94
src/views/courseList.vue

@@ -6,7 +6,7 @@
       <div class="inner">
         <div class="btn-box">
           <span @click="handleAdd">
-            <img src="../assets/common/icon-add.png">新建教材
+            <img src="../assets/common/icon-add.png" />新建教材
           </span>
           <!-- <el-button @click="handleAdd" size="small" type="primary"
             ><img src="../assets/common/icon-add.png">新建教材</el-button
@@ -65,11 +65,9 @@
                 />
               </el-select>
             </el-form-item>
-            <el-button
-              size="medium"
-              type="primary"
-              @click="onSubmit"
-            >查询</el-button>
+            <el-button size="medium" type="primary" @click="onSubmit"
+              >查询</el-button
+            >
           </el-form-item>
         </el-form>
         <div class="table-box">
@@ -84,36 +82,16 @@
               prop="name"
               width="150"
             />
-            <el-table-column
-              label="英文名"
-              prop="name_english"
-              width="150"
-            />
-            <el-table-column
-              label="作者"
-              prop="author"
-              width="100"
-            />
-            <el-table-column
-              label="版本"
-              prop="edition"
-              width="100"
-            />
-            <el-table-column
-              label="出版社"
-              prop="publisher"
-              width="150"
-            />
+            <el-table-column label="英文名" prop="name_english" width="150" />
+            <el-table-column label="作者" prop="author" width="100" />
+            <el-table-column label="版本" prop="edition" width="100" />
+            <el-table-column label="出版社" prop="publisher" width="150" />
             <el-table-column
               label="出版编号"
               prop="publish_number"
               width="100"
             />
-            <el-table-column
-              label="所属机构"
-              prop="org_name"
-              width="150"
-            />
+            <el-table-column label="所属机构" prop="org_name" width="150" />
             <el-table-column
               :formatter="handleStatus"
               label="发布状态"
@@ -128,32 +106,30 @@
             />
             <el-table-column fixed="right" label="操作" prop width="300">
               <template slot-scope="scope">
-                <el-button
-                  type="text"
-                  @click="handleClick(scope.row)"
-                >编辑</el-button>
-                <el-button
-                  type="text"
-                  @click="handleView(scope.row)"
-                >预览</el-button>
+                <el-button type="text" @click="handleClick(scope.row)"
+                  >编辑</el-button
+                >
+                <el-button type="text" @click="handleView(scope.row)"
+                  >预览</el-button
+                >
                 <el-button
                   type="text"
                   @click="handleUp(scope.row, scope.$index)"
-                >{{
-                  scope.row.publish_status === 0 ? "上架" : "下架"
-                }}</el-button>
+                  >{{
+                    scope.row.publish_status === 0 ? "上架" : "下架"
+                  }}</el-button
+                >
                 <el-button
                   type="text"
                   @click="handleEdit(scope.row, scope.$index)"
-                >教材信息</el-button>
-                <el-button
-                  type="text"
-                  @click="handleDiscount(scope.row)"
-                >优惠码</el-button>
-                <el-button
-                  type="text"
-                  @click="handleDel(scope.row)"
-                >删除</el-button>
+                  >教材信息</el-button
+                >
+                <el-button type="text" @click="handleDiscount(scope.row)"
+                  >优惠码</el-button
+                >
+                <el-button type="text" @click="handleDel(scope.row)"
+                  >删除</el-button
+                >
               </template>
             </el-table-column>
           </el-table>
@@ -183,11 +159,7 @@
           label-width="90px"
           prop="name"
         >
-          <el-input
-            v-model="formDialog.name"
-            autocomplete="off"
-            name="name"
-          />
+          <el-input v-model="formDialog.name" autocomplete="off" name="name" />
         </el-form-item>
         <el-form-item
           class="label-input"
@@ -289,28 +261,21 @@
                     <el-radio label="1" v-model="formDialog.publish_status">上架</el-radio>
                 </el-form-item>-->
         <el-form-item label="发布范围" label-width="90px" prop="publish_scope">
-          <el-radio
-            v-model="formDialog.publish_scope"
-            :label="0"
-          >机构内用户可见</el-radio>
-          <el-radio
-            v-model="formDialog.publish_scope"
-            :label="1"
-          >所有用户可见</el-radio>
+          <el-radio v-model="formDialog.publish_scope" :label="0"
+            >机构内用户可见</el-radio
+          >
+          <el-radio v-model="formDialog.publish_scope" :label="1"
+            >所有用户可见</el-radio
+          >
         </el-form-item>
         <el-form-item label="主题颜色" label-width="90px" prop="theme_color">
-          <el-radio
-            v-model="formDialog.theme_color"
-            label="red"
-          >红色</el-radio>
-          <el-radio
-            v-model="formDialog.theme_color"
-            label="green"
-          >绿色</el-radio>
-          <el-radio
-            v-model="formDialog.theme_color"
-            label="brown"
-          >棕色</el-radio>
+          <el-radio v-model="formDialog.theme_color" label="red">红色</el-radio>
+          <el-radio v-model="formDialog.theme_color" label="green"
+            >绿色</el-radio
+          >
+          <el-radio v-model="formDialog.theme_color" label="brown"
+            >棕色</el-radio
+          >
         </el-form-item>
         <el-form-item label="教材图片" label-width="90px" prop="fileList">
           <el-upload
@@ -333,11 +298,9 @@
       </el-form>
       <div slot="footer" class="dialog-footer">
         <el-button @click="dialogFlag = false">取 消</el-button>
-        <el-button
-          :loading="loading"
-          type="primary"
-          @click="submitCourse"
-        >确 定</el-button>
+        <el-button :loading="loading" type="primary" @click="submitCourse"
+          >确 定</el-button
+        >
       </div>
     </el-dialog>
   </div>
@@ -405,7 +368,7 @@ export default {
         picture_id: "",
         id: "",
         publisher: "",
-        theme_color: ''
+        theme_color: "",
       },
       agencyList: [
         {
@@ -548,6 +511,7 @@ export default {
     },
     // 预览
     handleView(row) {
+      sessionStorage.setItem("Bookdetail", JSON.stringify(row));
       this.$router.push("/courseview?bookId=" + row.id);
     },
     // 优惠码
@@ -571,7 +535,7 @@ export default {
         picture_id: "",
         id: "",
         publisher: "",
-        theme_color: ''
+        theme_color: "",
       };
       this.agency = "";
       this.fileList = [];
@@ -580,10 +544,12 @@ export default {
     // 新建教材提交
     submitCourse() {
       const _this = this;
-      _this.$refs.formDialog.validate(valid => {
+      _this.$refs.formDialog.validate((valid) => {
         _this.formDialog.name = _this.formDialog.name.trim();
         _this.formDialog.author = _this.formDialog.author.trim();
-        if (_this.formDialog.description !== "") { _this.formDialog.description = _this.formDialog.description.trim(); }
+        if (_this.formDialog.description !== "") {
+          _this.formDialog.description = _this.formDialog.description.trim();
+        }
         if (valid) {
           // if (
           //   (!this.formDialog.price && this.formDialog.price != 0)
@@ -617,7 +583,7 @@ export default {
           this.formDialog.publish_status = 1;
           let data = JSON.parse(JSON.stringify(_this.formDialog));
           getContent(MethodName, data)
-            .then(res => {
+            .then((res) => {
               this.$message.success("操作成功");
               if (_this.formDialog.id) {
                 this.$set(_this.tableData, this.rowIndex, data);
@@ -650,7 +616,7 @@ export default {
         publish_status: this.form.publish_status,
         is_control_publish_scope: "false",
       };
-      getContent(MethodName, data).then(res => {
+      getContent(MethodName, data).then((res) => {
         let _this = this;
         _this.tableData = res.book_list;
         _this.courseTotal = res.total_count;
@@ -667,7 +633,7 @@ export default {
       };
       let dataList = [];
       getContentFile(MethodName, data)
-        .then(res => {
+        .then((res) => {
           dataList = res.org_list;
           if (this.pageIndex === res.total_page) {
             // 获取到最后的值时,不再监听滚动条的动作,移除滚动事件
@@ -690,7 +656,7 @@ export default {
         audited_status: -1,
       };
       console.log("MethodName");
-      getContentFile(MethodName, data).then(res => {
+      getContentFile(MethodName, data).then((res) => {
         if (res && res.org_list.length > 0) {
           this.myOrgList = this.myOrgList.concat(res.org_list);
           this.diaMyOrgList = res.org_list;
@@ -704,7 +670,7 @@ export default {
         audited_status: 1,
       };
       console.log("MethodName");
-      getContentFile(MethodName, data).then(res => {
+      getContentFile(MethodName, data).then((res) => {
         if (res && res.org_list.length > 0) {
           this.diaMyOrgList = res.org_list;
         }
@@ -739,7 +705,9 @@ export default {
     },
     // 处理教材价格 失去焦点保留两位小数
     blurPrice() {
-      if (this.formDialog.price) { this.formDialog.price = Number(this.formDialog.price).toFixed(2); }
+      if (this.formDialog.price) {
+        this.formDialog.price = Number(this.formDialog.price).toFixed(2);
+      }
     },
     handleSuccess(response, file, fileList) {
       if (response.status == 1) {
@@ -787,7 +755,7 @@ export default {
         id: row.id,
       };
       getContent(MethodName, data)
-        .then(res => {
+        .then((res) => {
           this.formDialog = {
             id: res.id,
             name: res.name,
@@ -804,6 +772,7 @@ export default {
             theme_color: res.theme_color,
             edition: res.edition,
           };
+          sessionStorage.setItem("Bookdetail", JSON.stringify(this.formDialog));
           if (res.picture_url) {
             let obj = {
               name: "",
@@ -832,7 +801,7 @@ export default {
             id: row.id,
           };
           getContent(MethodName, data)
-            .then(res => {
+            .then((res) => {
               this.currentPage = 1;
               this.getList();
               this.$message({
@@ -859,7 +828,7 @@ export default {
         data.publish_status = 0;
         updataData.publish_status = 0;
       }
-      getContent(Mname, data).then(res => {
+      getContent(Mname, data).then((res) => {
         this.$message.success("操作成功");
         this.$set(this.tableData, index, updataData);
       });