Parcourir la source

update 语音矩阵全屏

dusenyao il y a 3 ans
Parent
commit
881ab42ac1

+ 152 - 25
src/components/Adult/preview/VoiceMatrix.vue

@@ -13,9 +13,17 @@
         </span>
       </div>
       <div v-show="hasSelectedCell" class="audio-simple">
-        <img :src="playing ? voicePlaySrc : voicePauseSrc" @click="playAudio">
+        <img
+          class="audio-simple-image"
+          :src="playing ? voicePlaySrc : voicePauseSrc"
+          @click="playAudio"
+        >
         <span
-          :class="['Repeat-16', isRepeat ? '' : 'disabled']"
+          :class="[
+            'Repeat-16',
+            'audio-simple-repeat',
+            isRepeat ? '' : 'disabled'
+          ]"
           @click="isRepeat = !isRepeat"
         />
       </div>
@@ -310,19 +318,21 @@
         <div class="matrix-bottom" @mouseenter="clearSelectCell" />
       </div>
     </div>
-
+    <!-- 录音 -->
     <div class="voice-luyin">
       <soundrecord
+        ref="luyin"
         type="promax"
         class="luyin-box"
         :file-name="fileName"
         :select-data="selectData"
         @getWavblob="getWavblob"
         @getSelectData="getSelectData"
-        @handleParentPlay="handleParentPlay"
+        @handleParentPlay="pauseOtherAudio"
         @sentPause="sentPause"
       />
       <audio-compare
+        :style="{ flex: 1 }"
         :theme-color="themeColor"
         :wavblob="wavblob"
         :url="mp3Url"
@@ -334,6 +344,20 @@
         :handle-change-stop-audio="handleChangeStopAudio"
         @playing="playChange"
       />
+      <span class="fullscreen" @click="fullScreen">
+        全屏模式
+        <el-image :src="fullscreenSrc" />
+      </span>
+    </div>
+    <div :id="`screen-${cid}`" class="voice-full-screen">
+      <voice-fullscreen
+        v-if="isFull"
+        :theme-color="themeColor"
+        :cur-que="curQue"
+        :mp3="mp3Url"
+        @exitFullscreen="exitFullscreen"
+        @changeIsFull="changeIsFull"
+      />
     </div>
   </div>
 </template>
@@ -343,16 +367,23 @@ import Bus from "./components/Bus.js";
 import AudioLine from "./AudioLine.vue";
 import Soundrecord from "./Soundrecord.vue";
 import AudioCompare from "./AudioCompareMatrix.vue";
+import VoiceFullscreen from "./VoiceMatrixFullscreen.vue";
 
 export default {
   components: {
     AudioLine,
     Soundrecord,
-    AudioCompare
+    AudioCompare,
+    VoiceFullscreen
   },
   props: ["curQue", "themeColor"],
   data() {
     return {
+      // 组件id
+      cid: Math.random()
+        .toString(36)
+        .substr(2, 10),
+      isFull: false,
       curTime: 0,
       playing: false,
       stopAudio: true,
@@ -416,18 +447,25 @@ export default {
     },
 
     voicePauseSrc() {
-      let themeColor = this.themeColor;
+      const themeColor = this.themeColor;
       if (themeColor.length === 0 || themeColor === "red") {
-        return require("../../../assets/NPC/play-red.png");
+        return require("@/assets/NPC/play-red.png");
       }
-      return require(`../../../assets/NPC/play-${themeColor}.png`);
+      return require(`@/assets/NPC/play-${themeColor}.png`);
     },
     voicePlaySrc() {
-      let themeColor = this.themeColor;
+      const themeColor = this.themeColor;
+      if (themeColor.length === 0 || themeColor === "red") {
+        return require("@/assets/NPC/icon-voice-play-red.png");
+      }
+      return require(`@/assets/NPC/icon-voice-play-${themeColor}.png`);
+    },
+    fullscreenSrc() {
+      const themeColor = this.themeColor;
       if (themeColor.length === 0 || themeColor === "red") {
-        return require("../../../assets/NPC/icon-voice-play-red.png");
+        return require("@/assets/NPC/full-screen-red.png");
       }
-      return require(`../../../assets/NPC/icon-voice-play-${themeColor}.png`);
+      return require(`@/assets/NPC/full-screen-${themeColor}.png`);
     }
   },
   watch: {
@@ -436,10 +474,23 @@ export default {
     }
   },
   created() {
-    Bus.$on("audioPause", () => {
+    Bus.$on("audioPause", id => {
+      if (this.cid === id) return;
+      if (this.$refs.luyin.microphoneStatus) this.$refs.luyin.microphone();
       this.handleParentPlay();
     });
   },
+
+  mounted() {
+    document
+      .querySelector("body")
+      .addEventListener("click", this.restoreAudioStatus);
+  },
+  beforeDestroy() {
+    document
+      .querySelector("body")
+      .removeEventListener("click", this.restoreAudioStatus);
+  },
   methods: {
     // 鼠标移入移出
     matrixCellMouseenter(i, j, type) {
@@ -491,6 +542,32 @@ export default {
       }
     },
 
+    // 判断 click 点击是否语音矩阵可操作区域
+    restoreAudioStatus(event) {
+      const whitePath = [
+        "column-green",
+        "column-red",
+        "column-brown",
+        "matrix-checkbox-column-",
+        "matrix-checkbox-row-",
+        "audio-simple-image",
+        "audio-simple-repeat",
+        "luyin-box"
+      ];
+
+      let operable = event.path.some(item => {
+        let className = item.className;
+        if (!className) return false;
+        return whitePath.some(path => className.includes(path));
+      });
+      if (!operable) {
+        this.selectedLine = { type: "", index: -1 };
+        this.selectCell = { row: -1, column: -1 };
+        if (this.playing) this.handleParentPlay();
+        if (this.unWatch) this.unWatch();
+      }
+    },
+
     checkboxMouseenter(isSelected, type) {
       if (!isSelected) return this.clearSelectCell();
       if (type === "row") this.selectColumn = -1;
@@ -530,12 +607,10 @@ export default {
       this.lrcArray = [];
       let { type, index } = this.selectedLine;
       if (type.length > 0 && index >= 0 && type === "row") {
-        this.curQue.voiceMatrix.matrix[index].forEach(
-          item => {
-            let data = this.getLrcData(item);
-            if (data) this.lrcArray.push(data);
-          }
-        );
+        this.curQue.voiceMatrix.matrix[index].forEach(item => {
+          let data = this.getLrcData(item);
+          if (data) this.lrcArray.push(data);
+        });
         if (this.lrcArray.length > 0) this.lrcPlay(this.lrcArray[0], 0);
         return;
       }
@@ -586,7 +661,12 @@ export default {
     playChange(playing) {
       this.playing = playing;
       // 子组件通信,同时只能播放一个音频
-      if (playing) Bus.$emit("audioPause");
+      if (playing) Bus.$emit("audioPause", this.cid);
+    },
+
+    pauseOtherAudio() {
+      Bus.$emit("audioPause", this.cid);
+      this.stopAudio = true;
     },
 
     // 暂停音频播放
@@ -610,12 +690,10 @@ export default {
       if (type === "") return;
       let arr = [];
       if (type.length > 0 && index >= 0 && type === "row") {
-        this.curQue.voiceMatrix.matrix[index].forEach(
-          item => {
-            let data = this.getLrcData(item);
-            if (data) arr.push(data);
-          }
-        );
+        this.curQue.voiceMatrix.matrix[index].forEach(item => {
+          let data = this.getLrcData(item);
+          if (data) arr.push(data);
+        });
         this.matrixSelectLrc = arr;
         return;
       }
@@ -659,6 +737,45 @@ export default {
       this.isRecord = isRecord;
     },
 
+    pauseAudio() {
+      let audio = document.getElementsByTagName("audio");
+      audio.forEach(item => {
+        item.pause();
+      });
+    },
+    fullScreen() {
+      this.pauseAudio();
+      this.isFull = true;
+      this.goFullscreen();
+    },
+    goFullscreen() {
+      let element = document.getElementById(`screen-${this.cid}`);
+      if (element.requestFullscreen) {
+        element.requestFullscreen();
+      } else if (element.msRequestFullscreen) {
+        element.msRequestFullscreen();
+      } else if (element.mozRequestFullScreen) {
+        element.mozRequestFullScreen();
+      } else if (element.webkitRequestFullscreen) {
+        element.webkitRequestFullscreen();
+      }
+    },
+    exitFullscreen() {
+      this.isFull = false;
+      if (document.exitFullscreen) {
+        document.exitFullscreen();
+      } else if (document.msExitFullscreen) {
+        document.msExitFullscreen();
+      } else if (document.mozCancelFullScreen) {
+        document.mozCancelFullScreen();
+      } else if (document.webkitExitFullscreen) {
+        document.webkitExitFullscreen();
+      }
+    },
+    changeIsFull() {
+      this.isFull = false;
+    },
+
     handleChangeTime({ begin_time, end_time }) {
       if (this.unWatch) this.unWatch();
       this.handleParentPlay();
@@ -1154,6 +1271,16 @@ $select-color-brown-active: #a37557;
     align-items: center;
     padding: 3px 16px;
     height: 40px;
+
+    .fullscreen {
+      cursor: pointer;
+
+      .el-image {
+        width: 16px;
+        height: 16px;
+        vertical-align: text-bottom;
+      }
+    }
   }
 }
 </style>

+ 780 - 0
src/components/Adult/preview/VoiceMatrixFullscreen.vue

@@ -0,0 +1,780 @@
+<template>
+  <div :class="['voicefull', bgIndex === 0 ? 'bg1' : 'bg2']">
+    <div
+      class="voicefull-top"
+      @mouseover="setTopShow(true)"
+      @mouseleave="setTopShow(false)"
+    >
+      <div :class="[isTopShow ? 'voicefull-top-show' : 'voicefull-top-hidden']">
+        <div class="top-left">
+          <div :class="['select-bg', bgIndex === 1 ? 'select-bg-blue' : '']">
+            <div :class="['bg-green-box', bgIndex === 1 ? 'active' : '']">
+              <span
+                :class="['bg-green', bgIndex === 1 ? 'active' : '']"
+                @click="changeBg(1)"
+              />
+            </div>
+            <div :class="['bg-white-box', bgIndex === 0 ? 'active' : '']">
+              <span
+                :class="['bg-white', bgIndex === 0 ? 'active' : '']"
+                @click="changeBg(0)"
+              />
+            </div>
+          </div>
+          <div
+            :class="['set-fontSize', bgIndex === 1 ? 'set-fontSize-green' : '']"
+          >
+            <template v-if="hzSize >= 34">
+              <span
+                :class="[
+                  'font-jian-black',
+                  bgIndex === 1 ? 'font-jian-yellow' : ''
+                ]"
+                @click="setFontSize('-')"
+              />
+            </template>
+            <template v-else>
+              <span
+                :class="[
+                  'font-jian-black',
+                  bgIndex === 1
+                    ? 'font-jian-yellow-disabled'
+                    : 'font-jian-white-disabled'
+                ]"
+              />
+            </template>
+            <span
+              :class="[
+                'font-img-black',
+                bgIndex === 1 ? 'font-img-yellow' : ''
+              ]"
+            />
+            <template v-if="hzSize <= 76">
+              <span
+                :class="[
+                  'font-jia-black',
+                  bgIndex === 1 ? 'font-jia-yellow' : ''
+                ]"
+                @click="setFontSize('+')"
+              />
+            </template>
+            <template v-else>
+              <span
+                :class="[
+                  'font-jia-black',
+                  bgIndex === 1
+                    ? 'font-jia-yellow-disabled'
+                    : 'font-jia-white-disabled'
+                ]"
+              />
+            </template>
+          </div>
+          <div
+            :class="['op-btn', bgIndex === 1 ? 'op-btn-green' : '']"
+            @click="changeStatus('isKeyboard')"
+          >
+            <span
+              :class="[
+                'keyboard-icon',
+                !isKeyboard ? 'disabled' : '',
+                isKeyboard && bgIndex === 1 ? 'keyboard-icon-yellow' : ''
+              ]"
+            />
+          </div>
+        </div>
+        <div class="top-middle">
+          <template v-if="mp3">
+            <audio-line-sentence
+              ref="audioLineSent"
+              :mp3="mp3"
+              :get-cur-time="getCurTime"
+              audio-id="artPraAudioId"
+              :stop-audio="stopAudio"
+              :width="120"
+              :hide-slider="true"
+              :bg="bg"
+              :ed="ed"
+              :cur-time="curTime"
+              :max-time="maxTime"
+              :bg-index="bgIndex"
+              :is-repeat="isRepeat"
+              :is-auto="isAuto"
+              @playChange="playChange"
+            />
+          </template>
+          <div
+            :class="['op-btn', bgIndex === 1 ? 'op-btn-green' : '']"
+            @click="setStatus"
+          >
+            <span
+              :class="[
+                'repeat-icon',
+                !isRepeat && !isAuto ? 'disabled' : '',
+                !isRepeat && isAuto ? 'auto-icon' : '',
+                isRepeat && bgIndex === 1 ? 'repeat-icon-yellow' : '',
+                !isRepeat && isAuto && bgIndex === 1 ? 'auto-icon-yellow' : ''
+              ]"
+            />
+          </div>
+        </div>
+        <div
+          :class="['op-btn', bgIndex === 1 ? 'op-btn-green' : '']"
+          @click="exitFullScreen"
+        >
+          <span
+            :class="['close-icon', bgIndex === 1 ? 'close-icon-white' : '']"
+          />
+        </div>
+      </div>
+    </div>
+
+    <div class="voicefull-content" />
+
+    <div
+      class="voicefull-bottom"
+      @mouseover="setBottomShow(true)"
+      @mouseleave="setBottomShow(false)"
+    >
+      <div :class="['voicefull-bottom-show', isBottomShow ? '' : 'hidden']">
+        <div class="bottom-left">
+          <soundrecorddiff
+            ref="Soundrecorddiff"
+            :bg-index="bgIndex"
+            @handleWav="handleWav"
+            @getWavblob="getWavblob"
+            @handleParentPlay="handleParentPlay"
+            @sentPause="sentPause"
+            @getRerordStatus="getRerordStatus"
+            @getMicrophoneStatus="getMicrophoneStatus"
+            @getPlayStatus="getPlayStatus"
+          />
+          <div
+            v-if="isShowCompare"
+            :class="['compare-box', bgIndex === 1 ? 'compare-box-white' : '']"
+          >
+            <audio-compare
+              :bg-index="bgIndex"
+              type="full"
+              :theme-color="themeColor"
+              :url="mp3"
+              :bg="bg"
+              :ed="ed"
+              :wavblob="wavblob"
+              :get-cur-time="getCurCompareTime"
+              :sent-pause="sentPause"
+              :is-record="isRecord"
+              :handle-change-stop-audio="handleChangeStopAudio"
+              :get-play-status="getPlayStatus"
+            />
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import AudioLineSentence from "./AudioLineSentence.vue";
+import Soundrecorddiff from "./Soundrecorddiff.vue";
+import AudioCompare from "./AudioCompare.vue";
+import Wordcard from "./components/Wordcard.vue";
+
+export default {
+  components: {
+    AudioLineSentence,
+    Soundrecorddiff,
+    AudioCompare,
+    Wordcard
+  },
+  props: ["mp3", "curQue", "themeColor"],
+  data() {
+    return {
+      hzSize: 48,
+      bgIndex: 1,
+      maxTime: 0,
+      item: null,
+      bg: 0,
+      ed: 0,
+      curTime: 0,
+      stopAudio: false,
+      isShowCompare: false,
+      clientY: 0,
+      top: 0,
+      left: 0,
+      isShow: false,
+      curWordTime: 0,
+      isPlaying: false,
+      isAuto: false,
+      key: "isRepeat",
+      isKeyboard: true,
+      isTopShow: false,
+      isBottomShow: false,
+      isRecording: false,
+      recordPlaying: false,
+      fileName: "",
+      // 底色行、列
+      selectRow: -1,
+      selectColumn: -1,
+      // 行、列选中
+      selectedLine: {
+        type: "",
+        index: 0
+      },
+      // 点击选中
+      selectCell: {
+        row: -1,
+        column: -1
+      },
+      isRepeat: false,
+      // 跟读所需属性
+      wavblob: null,
+      isRecord: false,
+      matrixSelectLrc: null
+    };
+  },
+  computed: {
+    pySize() {
+      return this.hzSize / 1.5;
+    },
+    enSize() {
+      return this.hzSize / 2;
+    },
+
+    hasSelectedCell() {
+      let { type, index } = this.selectedLine;
+      let { row, column } = this.selectCell;
+      return (type.length > 0 && index >= 0) || (row >= 0 && column >= 0);
+    },
+    selectData() {
+      let { type, index } = this.selectedLine;
+      let { row, column } = this.selectCell;
+      return {
+        type: type.length > 0 && index >= 0 ? type : "cell",
+        index,
+        row,
+        column
+      };
+    }
+  },
+  watch: {
+    isRecording(newVal) {
+      if (newVal) {
+        this.isBottomShow = newVal;
+      }
+    },
+    recordPlaying(newVal) {
+      if (newVal) {
+        this.isBottomShow = newVal;
+      }
+    },
+    isShow(val) {
+      if (val) {
+        setTimeout(() => {
+          this.cardHeight = this.$refs.wordcard.offsetHeight;
+          if (this.screenHeight - this.clientY > this.cardHeight) {
+            this.top = this.clientY + 20;
+          } else {
+            this.top = this.clientY - this.cardHeight - 30;
+          }
+        }, 50);
+      }
+    }
+  },
+  created() {
+    document.addEventListener("keyup", e => {
+      if (this.isKeyboard) {
+      }
+    });
+
+    [
+      "fullscreenchange",
+      "mozfullscreenchange",
+      "webkitfullscreenchange",
+      "msfullscreenchange"
+    ].forEach(event => {
+      document.addEventListener(event, () => {
+        let isFullscreen = Boolean(
+          document.fullScreen ||
+            document.mozFullScreen ||
+            document.webkitIsFullScreen ||
+            document.webkitFullScreen ||
+            document.msFullScreen
+        );
+        if (!isFullscreen) this.changeFullScreen();
+      });
+    });
+  },
+  beforeDestroy() {
+    document.removeEventListener("keyup");
+    [
+      "fullscreenchange",
+      "mozfullscreenchange",
+      "webkitfullscreenchange",
+      "msfullscreenchange"
+    ].forEach(event => {
+      document.removeEventListener(event);
+    });
+  },
+  // 方法集合
+  methods: {
+    setTopShow(bool) {
+      this.isTopShow = bool;
+    },
+    setBottomShow(bool) {
+      if (!this.recordPlaying && !this.isRecording) {
+        this.isBottomShow = bool;
+      }
+    },
+    getPlayStatus(bool) {
+      this.recordPlaying = bool;
+    },
+    setFontSize(type) {
+      if (this.hzSize >= 34 || this.hzSize <= 76) {
+        type === "+" ? (this.hzSize += 4) : (this.hzSize -= 4);
+      }
+    },
+    playChange(bool) {
+      this.isPlaying = bool;
+    },
+    changeStatus(key) {
+      this[key] = !this[key];
+    },
+    setStatus() {
+      if (this.key === "isRepeat") {
+        if (this.isRepeat) {
+          this.isRepeat = false;
+          this.isAuto = true;
+          this.key = "isAuto";
+        } else {
+          this.isRepeat = true;
+          this.key = "isRepeat";
+        }
+      } else if (this.key === "isAuto") {
+        if (this.isAuto) {
+          this.isRepeat = false;
+          this.isAuto = false;
+          this.key = "isRepeat";
+        }
+      }
+    },
+    getRerordStatus(bool) {
+      this.isShowCompare = bool;
+    },
+    getMicrophoneStatus(bool) {
+      this.isRecording = bool;
+    },
+    getWavblob(wavblob) {
+      this.wavblob = wavblob;
+    },
+    sentPause(isRecord) {
+      this.isRecord = isRecord;
+    },
+    getCurTime(curTime) {
+      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 if (this.isAuto) {
+        let time = curTime * 1000;
+        if (time > this.ed) {
+          this.curTime = this.bg;
+          this.$refs.audioLineSent.onTimeupdateTime(this.bg / 1000);
+        } else {
+          this.curTime = curTime * 1000;
+        }
+      } else {
+        this.curTime = curTime * 1000;
+      }
+    },
+    getCurCompareTime(curTime) {
+      this.curTime = curTime * 1000;
+    },
+    getCurWordTime(curTime) {
+      this.curWordTime = curTime * 1000;
+    },
+    changeBg(bgIndex) {
+      this.bgIndex = bgIndex;
+    },
+    pauseAudio() {
+      let audio = document.getElementsByTagName("audio");
+      audio.forEach(item => {
+        item.pause();
+      });
+    },
+    exitFullScreen() {
+      this.pauseAudio();
+      this.$emit("exitFullscreen");
+    },
+    changeFullScreen() {
+      this.pauseAudio();
+      this.$emit("changeIsFull");
+    },
+    handleWav(data) {},
+    // 录音时暂停音频播放
+    handleParentPlay() {
+      this.stopAudio = true;
+    },
+    // 音频播放时改变布尔值
+    handleChangeStopAudio() {
+      this.stopAudio = false;
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.voicefull {
+  width: 100%;
+  height: 100vh;
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+
+  &.bg1 {
+    background: #fff;
+  }
+
+  &.bg2 {
+    background: linear-gradient(180deg, #274533 0%, #385f45 100%);
+  }
+
+  &-top {
+    height: 136px;
+    width: 100%;
+    padding: 0 40px;
+
+    .voicefull-top-hidden {
+      width: 100%;
+      height: 136px;
+      visibility: hidden;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+    }
+    .voicefull-top-show {
+      width: 100%;
+      height: 136px;
+      visibility: visible;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+    }
+    .top-left {
+      display: flex;
+      justify-content: flex-start;
+      align-items: center;
+    }
+    .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;
+      margin-right: 32px;
+
+      &.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%;
+
+          cursor: pointer;
+          &.bg-white {
+            background: #fff;
+          }
+          &.bg-green {
+            background: linear-gradient(180deg, #274533 0%, #385f45 100%);
+          }
+        }
+      }
+    }
+
+    .set-fontSize {
+      padding: 0 20px;
+      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);
+      }
+      > span {
+        width: 24px;
+        height: 24px;
+        margin: 0 4px;
+        &.font-jian {
+          &-black {
+            background: url("../../../assets/NPC/jian-black.png") no-repeat left
+              top;
+            background-size: 100% 100%;
+            cursor: pointer;
+          }
+          &-yellow {
+            background: url("../../../assets/NPC/jian-white.png") no-repeat left
+              top;
+            background-size: 100% 100%;
+            cursor: pointer;
+          }
+          &-white-disabled {
+            background: url("../../../assets/NPC/jian-white-disabled.png")
+              no-repeat left top;
+            background-size: 100% 100%;
+            cursor: pointer;
+          }
+          &-yellow-disabled {
+            background: url("../../../assets/NPC/jian-yellow-disabled.png")
+              no-repeat left top;
+            background-size: 100% 100%;
+            cursor: pointer;
+          }
+        }
+        &.font-img {
+          &-black {
+            background: url("../../../assets/NPC/fontSize-black.png") no-repeat
+              left top;
+            background-size: 100% 100%;
+          }
+          &-yellow {
+            background: url("../../../assets/NPC/fontSize-white.png") no-repeat
+              left top;
+            background-size: 100% 100%;
+          }
+        }
+        &.font-jia {
+          &-black {
+            background: url("../../../assets/NPC/jia-black.png") no-repeat left
+              top;
+            background-size: 100% 100%;
+            cursor: pointer;
+          }
+          &-yellow {
+            background: url("../../../assets/NPC/jia-white.png") no-repeat left
+              top;
+            background-size: 100% 100%;
+            cursor: pointer;
+          }
+          &-white-disabled {
+            background: url("../../../assets/NPC/jia-white-disabled.png")
+              no-repeat left top;
+            background-size: 100% 100%;
+            cursor: pointer;
+          }
+          &-yellow-disabled {
+            background: url("../../../assets/NPC/jia-yellow-disabled.png")
+              no-repeat left top;
+            background-size: 100% 100%;
+            cursor: pointer;
+          }
+        }
+      }
+    }
+
+    .top-middle {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      .audio-box {
+        width: 56px;
+        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);
+
+    &-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%;
+    }
+    &.auto-icon {
+      background: url("../../../assets/icon/Auto-24-next-red.png") no-repeat
+        left top;
+      background-size: 100% 100%;
+      &-yellow {
+        background: url("../../../assets/icon/Auto-24-next-yellow.png")
+          no-repeat left top;
+        background-size: 100% 100%;
+      }
+    }
+  }
+  .keyboard-icon {
+    background: url("../../../assets/icon/enter-24-keyboard-red.png") no-repeat
+      left top;
+    background-size: 100% 100%;
+    &.disabled {
+      background: url("../../../assets/icon/enter-24-keyboard-disable-Black.png")
+        no-repeat left top;
+      background-size: 100% 100%;
+    }
+    &-yellow {
+      background: url("../../../assets/icon/enter-24-keyboard-yellow.png")
+        no-repeat left top;
+      background-size: 100% 100%;
+    }
+  }
+
+  &-content {
+    flex: 1;
+    width: 100%;
+    display: flex;
+    align-items: center;
+  }
+
+  &-bottom {
+    height: 136px;
+    width: 100%;
+
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding-right: 40px;
+
+    .voicefull-bottom-show {
+      height: 136px;
+      width: 100%;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      visibility: visible;
+
+      &.hidden {
+        visibility: hidden;
+      }
+    }
+
+    .bottom-left {
+      display: flex;
+      justify-content: flex-start;
+      align-items: center;
+
+      .compare-box {
+        height: 56px;
+        padding: 16px 16px;
+
+        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;
+        }
+      }
+    }
+  }
+}
+</style>
+
+<style lang="scss">
+.NPC-Big-Book-preview-green {
+  .bg1 {
+    .repeat-icon {
+      background: url("../../../assets/icon/Repeat-24-normal-Green.png")
+        no-repeat left top;
+      background-size: 100% 100%;
+    }
+  }
+}
+
+.NPC-Big-Book-preview-brown {
+  .bg1 {
+    .repeat-icon {
+      background: url("../../../assets/icon/Repeat-24-normal-Brown.png")
+        no-repeat left top;
+      background-size: 100% 100%;
+    }
+  }
+}
+</style>