guanchunjie 3 years ago
parent
commit
256e704682

+ 202 - 3
src/components/Adult/inputModules/Neword.vue

@@ -32,7 +32,51 @@
         </div>
               
       </div>
-
+      <div class="adult-book-input-item">
+        <span class="adult-book-lable">题目音频:</span>
+        <Upload
+          :changeFillId="changeMp3"
+          :datafileList="curQue.mp3_list"
+          :filleNumber="mp3Number"
+          :uploadType="'mp3'"
+          :handleMp3Base64="handleChange"
+        />
+      </div>
+      <div class="adult-book-input-item">
+        <span class="adult-book-lable">题目lrc:</span>
+        <Upload
+          :changeFillId="changeLrc"
+          :datafileList="curQue.lrc_list"
+          :filleNumber="mp3Number"
+          :uploadType="'lrc'"
+        />
+      </div>
+      <div class="adult-book-input-item">
+        <span class="adult-book-lable"></span>
+        <el-button
+          type="primary"
+          size="small"
+          class="distribution"
+          @click="parseLrcFile"
+        >
+          分配lrc
+        </el-button>
+      </div>
+      <div class="lrc-box">
+        <div
+          v-if="this.curQue.wordTime && this.curQue.wordTime.length > 0"
+          class="lrc-box"
+        >
+          <span>已有字幕时间节点</span>
+          <el-button type="text" @click="againWordTime">重新生成</el-button>
+        </div>
+        <template v-else>
+          <el-button v-if="!isWordTime" size="medium" @click="createWordTime"
+            >自动生成字幕节点</el-button
+          >
+          <p v-else>字幕节点生成中...请等待</p>
+        </template>
+      </div>
       <div
         class="Big-Book-main"
         v-for="(item, index) in curQue.option"
@@ -67,22 +111,30 @@
 <script>
 import Inputmodule from "../common/Inputmodule.vue";
 import NewordPhraseModule from "../common/NewordPhraseModule.vue";
-
+import { getWordTime, getContentFile } from "@/api/ajax";
+import Upload from "../common/Upload";
 export default {
   name: "Single",
   props: ["curQue", "changeCurQue"],
   components: {
     Inputmodule,
     NewordPhraseModule,
+    Upload,
   },
   data() {
     return {
+      mp3Number: 1,
+      isWordTime: false,
       data_structure: {
         type: "NewWord_chs",
         name: "生词",
         title: "",
         isInfor: true,
         titleBg: "themeColor", //标题背景颜色
+        mp3_list: [],
+        lrc_list: [],
+        taskId: [],
+        wordTime: null,
         option: [
           [
             {
@@ -112,7 +164,7 @@ export default {
       let last = this.curQue.option[leg - 1];
       let res_data = JSON.parse(JSON.stringify(this.data_structure));
       let obj = res_data.option[0];
-      this.curQue.option.push(obj);
+      obj.index = this.curQue.option.push(obj);
     },
     deleteGroup(index, sIndex) {
       if (this.curQue.option[0].length == 1) {
@@ -135,6 +187,140 @@ export default {
     delsItem(index) {
       this.curQue.option.splice(index, 1);
     },
+    changeMp3(fileList) {
+      const articleImgList = JSON.parse(JSON.stringify(fileList));
+      const articleImgRes = [];
+      articleImgList.forEach((item) => {
+        if (item.response) {
+          const obj = {
+            name: item.name,
+            url: item.response.file_info_list[0].file_url,
+            id: "[FID##" + item.response.file_info_list[0].file_id + "##FID]",
+
+            media_duration: item.response.file_info_list[0].media_duration, //音频时长
+          };
+          articleImgRes.push(obj);
+        }
+      });
+      this.curQue.mp3_list = JSON.parse(JSON.stringify(articleImgRes));
+    },
+    parseLrcFile() {
+      let lrcList = this.curQue.lrc_list;
+      if (lrcList.length === 0) {
+        return this.$message.warning("请先上传lrc文件");
+      }
+      getContentFile("tool-ParseLRCFile", {
+        content_type: "FILE",
+        file_id: this.curQue.lrc_list[0].file_id,
+      }).then(({ lrc_list }) => {
+        let lrc_list_res = [];
+        lrc_list.forEach((item) => {
+          let obj = {
+            bg: item.begin_time,
+            ed: item.end_time,
+          };
+          lrc_list_res.push(obj);
+        });
+        this.curQue.wordTime = lrc_list_res;
+      });
+    },
+    getBase64(file) {
+      return new Promise(function (resolve, reject) {
+        let reader = new FileReader();
+        let imgResult = "";
+        reader.readAsDataURL(file);
+        reader.onload = function () {
+          imgResult = reader.result;
+        };
+        reader.onerror = function (error) {
+          reject(error);
+        };
+        reader.onloadend = function () {
+          resolve(imgResult);
+        };
+      });
+    },
+    createWordTime() {
+      if (this.curQue.taskId) {
+        let verseList = [];
+        this.curQue.option.forEach((item, index) => {
+          item.forEach((sItem, sIndex) => {
+            verseList.push(sItem.new_word);
+          });
+        });
+        if (verseList.length > 0) {
+          this.isWordTime = true;
+          let data = {
+            taskId: this.curQue.taskId,
+            verseList: JSON.stringify(verseList),
+            matchType: "chinese",
+            language: "ch",
+          };
+          getWordTime(data).then((res) => {
+            this.curQue.wordTime = res.data.result;
+            this.isWordTime = false;
+          });
+        }
+      } else {
+        this.$message.warning("请先上传音频");
+      }
+    },
+    againWordTime() {
+      this.isWordTime = false;
+      this.$set(this.curQue, "wordTime", []);
+    },
+    // 上传音频文件
+    handleChange(file, fileList) {
+      let _this = this;
+      _this.getBase64(file.raw).then((res) => {
+        let base_res = res.split("base64,");
+        let data = {
+          fileName: file.raw.name,
+          speechBase64: base_res[1],
+          language: "ch",
+        };
+        prepareTranscribe(data).then((res) => {
+          _this.$set(_this.curQue, "taskId", res.data.taskId);
+        });
+      });
+    },
+    changeLrc(fileList) {
+      let lrc_list = [];
+      fileList.forEach(({ response, name }) => {
+        if (response) {
+          let fileList = response.file_info_list[0];
+          lrc_list.push({
+            name,
+            duration: fileList.media_duration,
+            url: fileList.file_url,
+            id: "[FID##" + fileList.file_id + "##FID]",
+            file_id: fileList.file_id,
+          });
+        }
+      });
+      this.curQue.lrc_list = lrc_list;
+    },
+    // 根据lrc文件id 获取内容和起始和结束时间
+    parseLrcFile() {
+      let lrcList = this.curQue.lrc_list;
+      if (lrcList.length === 0) {
+        return this.$message.warning("请先上传lrc文件");
+      }
+      getContentFile("tool-ParseLRCFile", {
+        content_type: "FILE",
+        file_id: this.curQue.lrc_list[0].file_id,
+      }).then(({ lrc_list }) => {
+        let lrc_list_res = [];
+        lrc_list.forEach((item) => {
+          let obj = {
+            bg: item.begin_time,
+            ed: item.end_time,
+          };
+          lrc_list_res.push(obj);
+        });
+        this.curQue.wordTime = lrc_list_res;
+      });
+    },
   },
   //生命周期 - 创建完成(可以访问当前this实例)
   created() {},
@@ -150,6 +336,19 @@ export default {
       if (!this.curQue.hasOwnProperty("titleBg")) {
         this.$set(this.curQue, "titleBg", "themeColor");
       }
+      if (!this.curQue.hasOwnProperty("mp3_list")) {
+        this.$set(this.curQue, "mp3_list", []);
+      }
+      if (!this.curQue.hasOwnProperty("lrc_list")) {
+        this.$set(this.curQue, "lrc_list", []);
+      }
+      if (!this.curQue.hasOwnProperty("taskId")) {
+        this.$set(this.curQue, "taskId", "");
+      }
+      if (!this.curQue.hasOwnProperty("wordTime")) {
+        this.$set(this.curQue, "wordTime", null);
+      }
+
       // let data = JSON.parse(JSON.stringify(this.curQue));
       this.curQue.option.forEach((item) => {
         if (!item[0].pinyin_site) {

+ 151 - 85
src/components/Adult/preview/ArticleViewChs/NormalModelChs.vue

@@ -1,20 +1,39 @@
 <!--  -->
 <template>
   <div class="NNPE-ArticleView" v-if="curQue">
-    <div
-      class="aduioLine-box"
-      v-if="
-        curQue.mp3_list && curQue.mp3_list.length > 0 && curQue.mp3_list[0].id
-      "
-    >
-      <AudioLine
-        audioId="artNormalAudio"
-        :mp3="curQue.mp3_list[0].id"
-        :getCurTime="getCurTime"
-        :duration="curQue.mp3_list[0].media_duration"
-        :mp3Source="curQue.mp3_list[0].source"
-        ref="audioLine"
-      />
+    <div class="aduioLine-box aduioLine-practice">
+      <div class="aduioLine-content">
+        <template
+          v-if="
+            curQue.mp3_list &&
+            curQue.mp3_list.length > 0 &&
+            curQue.mp3_list[0].id
+          "
+        >
+          <AudioLine
+            audioId="artNormalAudio"
+            :mp3="curQue.mp3_list[0].id"
+            :getCurTime="getCurTime"
+            :duration="curQue.mp3_list[0].media_duration"
+            :mp3Source="curQue.mp3_list[0].source"
+            :width="590"
+            :ed="ed"
+            type="audioLine"
+            ref="audioLine"
+            @emptyEd="emptyEd"
+          />
+        </template>
+      </div>
+      <div class="aduioLine-right">
+        <span
+          :class="['pinyin-16', config.isShowPY ? '' : 'disabled']"
+          @click="changePinyin"
+        ></span>
+        <span
+          :class="['EN-16', config.isShowEN ? '' : 'disabled']"
+          @click="changeEN"
+        ></span>
+      </div>
     </div>
     <template v-if="resArr.length > 0">
       <div class="NPC-sentences-list">
@@ -35,7 +54,10 @@
                   handleChangeTime(
                     item.timeList &&
                       item.timeList[pItem.sentIndex] &&
-                      item.timeList[pItem.sentIndex].bg
+                      item.timeList[pItem.sentIndex].bg,
+                    item.timeList &&
+                      item.timeList[pItem.sentIndex] &&
+                      item.timeList[pItem.sentIndex].ed
                   )
                 "
                 @mouseover="handleMouseover(pItem)"
@@ -52,7 +74,7 @@
                     >
                       <span class="NNPE-words-box">
                         <span
-                          v-if="curQue.pyPosition == 'top'"
+                          v-if="curQue.pyPosition == 'top' && config.isShowPY"
                           :class="[
                             'NNPE-pinyin',
                             pItem.className ? pItem.className : '',
@@ -93,7 +115,9 @@
                           </template>
                         </span>
                         <span
-                          v-if="curQue.pyPosition == 'bottom'"
+                          v-if="
+                            curQue.pyPosition == 'bottom' && config.isShowPY
+                          "
                           :class="[
                             'NNPE-pinyin',
                             pItem.className ? pItem.className : '',
@@ -104,7 +128,7 @@
                       </span>
                       <span class="NNPE-words-box">
                         <span
-                          v-if="curQue.pyPosition == 'top'"
+                          v-if="curQue.pyPosition == 'top' && config.isShowPY"
                           :class="[
                             'NNPE-pinyin',
                             noFont.indexOf(item.wordsList[pIndex + 1].pinyin) >
@@ -142,7 +166,9 @@
                           >{{ item.wordsList[pIndex + 1].chs }}</span
                         >
                         <span
-                          v-if="curQue.pyPosition == 'bottom'"
+                          v-if="
+                            curQue.pyPosition == 'bottom' && config.isShowPY
+                          "
                           :class="[
                             'NNPE-pinyin',
                             noFont.indexOf(item.wordsList[pIndex + 1].pinyin) >
@@ -157,7 +183,7 @@
                     </template>
                     <template v-else>
                       <span
-                        v-if="curQue.pyPosition == 'top'"
+                        v-if="curQue.pyPosition == 'top' && config.isShowPY"
                         class="NNPE-pinyin"
                         :class="[
                           pItem.padding ? 'padding' : '',
@@ -200,7 +226,7 @@
                         </template>
                       </span>
                       <span
-                        v-if="curQue.pyPosition == 'bottom'"
+                        v-if="curQue.pyPosition == 'bottom' && config.isShowPY"
                         class="NNPE-pinyin"
                         :class="[
                           pItem.padding ? 'padding' : '',
@@ -235,7 +261,7 @@ import { timeStrToSen } from "@/utils/index";
 import AudioLine from "../AudioLine.vue";
 export default {
   name: "NormalModelChs",
-  props: ["curQue", "noFont"],
+  props: ["curQue", "noFont", "config"],
   components: {
     AudioLine,
   },
@@ -254,6 +280,7 @@ export default {
       articleImg: {}, // 文章图片
       paraIndex: -1, //段落索引
       sentIndex: -1, // 句子索引
+      ed: undefined,
     };
   },
   computed: {
@@ -268,6 +295,18 @@ export default {
   watch: {},
   //方法集合
   methods: {
+    //拼音的显示和隐藏
+    changePinyin() {
+      if (this.config.isHasPY) {
+        this.$emit("changeConfig", "isShowPY");
+      }
+    },
+    // 英文的显示和隐藏
+    changeEN() {
+      if (this.config.isHasEN) {
+        this.$emit("changeConfig", "isShowEN");
+      }
+    },
     getCurTime(curTime) {
       this.curTime = curTime * 1000;
     },
@@ -390,12 +429,16 @@ export default {
       return listRes;
     },
     //点击播放某个句子
-    handleChangeTime(time) {
+    handleChangeTime(time, ed) {
       if (time) {
         this.curTime = time;
         this.$refs.audioLine.onTimeupdateTime(time / 1000, true);
+        this.ed = ed;
       }
     },
+    emptyEd() {
+      this.ed = undefined;
+    },
     //经过每个词,高亮句子
     handleMouseover(pItem) {
       this.paraIndex = pItem.paraIndex;
@@ -428,6 +471,29 @@ export default {
 //@import url(); 引入公共css类
 .NNPE-ArticleView {
   width: 100%;
+  .aduioLine-practice {
+    display: flex;
+    justify-content: flex-start;
+    align-items: center;
+    .aduioLine-content {
+      flex: 1;
+    }
+    .aduioLine-right {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      width: 69px;
+      height: 40px;
+      box-sizing: border-box;
+      padding: 0 12px;
+      border-left: 1px solid rgba(0, 0, 0, 0.1);
+      > span {
+        width: 16px;
+        height: 16px;
+        cursor: pointer;
+      }
+    }
+  }
   .NPC-sentences-list {
     padding: 24px 0;
     color: rgba(0, 0, 0, 0.85);
@@ -567,75 +633,75 @@ export default {
   }
 }
 .NPC-Big-Book-preview-green {
-    .NNPE-ArticleView {
-        .NNPE-detail {
-            .NNPE-words {
-                &-box {
-                    > span {
-                        &.NNPE-chs {
-                            &.active {
-                                background: rgba(36, 185, 158, 0.15);
-                            }
-                            &.wordActive {
-                                color: rgba(36, 185, 158, 1);
-                            }
-                            .wordActive {
-                                color: rgba(36, 185, 158, 1);
-                            }
-                        }
-                    }
-                }
-                > span {
-                    &.NNPE-chs {
-                        &.active {
-                            background: rgba(36, 185, 158, 0.15);
-                        }
-                        &.wordActive {
-                            color: rgba(36, 185, 158, 1);
-                        }
-                        .wordActive {
-                            color: rgba(36, 185, 158, 1);
-                        }
-                    }
-                }
+  .NNPE-ArticleView {
+    .NNPE-detail {
+      .NNPE-words {
+        &-box {
+          > span {
+            &.NNPE-chs {
+              &.active {
+                background: rgba(36, 185, 158, 0.15);
+              }
+              &.wordActive {
+                color: rgba(36, 185, 158, 1);
+              }
+              .wordActive {
+                color: rgba(36, 185, 158, 1);
+              }
+            }
+          }
+        }
+        > span {
+          &.NNPE-chs {
+            &.active {
+              background: rgba(36, 185, 158, 0.15);
+            }
+            &.wordActive {
+              color: rgba(36, 185, 158, 1);
             }
+            .wordActive {
+              color: rgba(36, 185, 158, 1);
+            }
+          }
         }
+      }
     }
+  }
 }
 .NPC-Big-Book-preview-brown {
-    .NNPE-ArticleView {
-        .NNPE-detail {
-            .NNPE-words {
-                &-box {
-                    > span {
-                        &.NNPE-chs {
-                            &.active {
-                                background: rgba(189, 136, 101, 0.15);
-                            }
-                            &.wordActive {
-                                color: rgba(189, 136, 101, 1);
-                            }
-                            .wordActive {
-                                color: rgba(189, 136, 101, 1);
-                            }
-                        }
-                    }
-                }
-                > span {
-                    &.NNPE-chs {
-                        &.active {
-                            background: rgba(189, 136, 101, 0.15);
-                        }
-                        &.wordActive {
-                            color: rgba(189, 136, 101, 1);
-                        }
-                        .wordActive {
-                            color: rgba(189, 136, 101, 1);
-                        }
-                    }
-                }
+  .NNPE-ArticleView {
+    .NNPE-detail {
+      .NNPE-words {
+        &-box {
+          > span {
+            &.NNPE-chs {
+              &.active {
+                background: rgba(189, 136, 101, 0.15);
+              }
+              &.wordActive {
+                color: rgba(189, 136, 101, 1);
+              }
+              .wordActive {
+                color: rgba(189, 136, 101, 1);
+              }
             }
+          }
         }
+        > span {
+          &.NNPE-chs {
+            &.active {
+              background: rgba(189, 136, 101, 0.15);
+            }
+            &.wordActive {
+              color: rgba(189, 136, 101, 1);
+            }
+            .wordActive {
+              color: rgba(189, 136, 101, 1);
+            }
+          }
+        }
+      }
     }
+  }
 }
 </style>

+ 75 - 19
src/components/Adult/preview/ArticleViewChs/PhraseModelChs.vue

@@ -1,19 +1,35 @@
 <!--  -->
 <template>
   <div class="NNPE-ArticleView" v-if="curQue">
-    <div
-      class="aduioLine-box"
-      v-if="
-        curQue.mp3_list && curQue.mp3_list.length > 0 && curQue.mp3_list[0].id
-      "
-    >
-      <AudioLine
-        audioId="artPhraseAudio"
-        :mp3="curQue.mp3_list[0].id"
-        :getCurTime="getCurTime"
-        :mp3Source="curQue.mp3_list[0].source"
-        ref="audioLine"
-      />
+    <div class="aduioLine-box aduioLine-practice">
+      <div class="aduioLine-content">
+        <template
+          v-if="
+            curQue.mp3_list &&
+            curQue.mp3_list.length > 0 &&
+            curQue.mp3_list[0].id
+          "
+        >
+          <AudioLine
+            audioId="artPhraseAudio"
+            :mp3="curQue.mp3_list[0].id"
+            :getCurTime="getCurTime"
+            :mp3Source="curQue.mp3_list[0].source"
+            :width="590"
+            ref="audioLine"
+          />
+        </template>
+      </div>
+      <div class="aduioLine-right">
+        <span
+          :class="['pinyin-16', config.isShowPY ? '' : 'disabled']"
+          @click="changePinyin"
+        ></span>
+        <span
+          :class="['EN-16', config.isShowEN ? '' : 'disabled']"
+          @click="changeEN"
+        ></span>
+      </div>
     </div>
     <template v-if="resArr.length > 0">
       <div class="NPC-sentences-list">
@@ -42,7 +58,7 @@
                     >
                       <span class="NNPE-words-box">
                         <span
-                          v-if="curQue.pyPosition == 'top'"
+                          v-if="curQue.pyPosition == 'top' && config.isShowPY"
                           :class="[
                             'NNPE-pinyin',
                             pItem.className ? pItem.className : '',
@@ -58,7 +74,9 @@
                           >{{ pItem.chs }}</span
                         >
                         <span
-                          v-if="curQue.pyPosition == 'bottom'"
+                          v-if="
+                            curQue.pyPosition == 'bottom' && config.isShowPY
+                          "
                           :class="[
                             'NNPE-pinyin',
                             pItem.className ? pItem.className : '',
@@ -69,7 +87,7 @@
                       </span>
                       <span class="NNPE-words-box">
                         <span
-                          v-if="curQue.pyPosition == 'top'"
+                          v-if="curQue.pyPosition == 'top' && config.isShowPY"
                           :class="[
                             'NNPE-pinyin',
                             noFont.indexOf(item.wordsList[pIndex + 1].pinyin) >
@@ -84,7 +102,9 @@
                           item.wordsList[pIndex + 1].chs
                         }}</span>
                         <span
-                          v-if="curQue.pyPosition == 'bottom'"
+                          v-if="
+                            curQue.pyPosition == 'bottom' && config.isShowPY
+                          "
                           :class="[
                             'NNPE-pinyin',
                             noFont.indexOf(item.wordsList[pIndex + 1].pinyin) >
@@ -99,7 +119,7 @@
                     </template>
                     <template v-else>
                       <span
-                        v-if="curQue.pyPosition == 'top'"
+                        v-if="curQue.pyPosition == 'top' && config.isShowPY"
                         class="NNPE-pinyin"
                         :class="[
                           pItem.padding ? 'padding' : '',
@@ -117,7 +137,7 @@
                         >{{ pItem.chs }}</span
                       >
                       <span
-                        v-if="curQue.pyPosition == 'bottom'"
+                        v-if="curQue.pyPosition == 'bottom' && config.isShowPY"
                         class="NNPE-pinyin"
                         :class="[
                           pItem.padding ? 'padding' : '',
@@ -174,6 +194,7 @@ export default {
     "themeColor",
     "noFont",
     "currentTreeID",
+    "config",
   ],
   components: {
     AudioLine,
@@ -232,6 +253,18 @@ export default {
   },
   //方法集合
   methods: {
+    //拼音的显示和隐藏
+    changePinyin() {
+      if (this.config.isHasPY) {
+        this.$emit("changeConfig", "isShowPY");
+      }
+    },
+    // 英文的显示和隐藏
+    changeEN() {
+      if (this.config.isHasEN) {
+        this.$emit("changeConfig", "isShowEN");
+      }
+    },
     getCurTime(curTime) {
       this.curTime = curTime;
     },
@@ -436,6 +469,29 @@ export default {
 //@import url(); 引入公共css类
 .NNPE-ArticleView {
   width: 100%;
+  .aduioLine-practice {
+    display: flex;
+    justify-content: flex-start;
+    align-items: center;
+    .aduioLine-content {
+      flex: 1;
+    }
+    .aduioLine-right {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      width: 69px;
+      height: 40px;
+      box-sizing: border-box;
+      padding: 0 12px;
+      border-left: 1px solid rgba(0, 0, 0, 0.1);
+      > span {
+        width: 16px;
+        height: 16px;
+        cursor: pointer;
+      }
+    }
+  }
   .NPC-sentences-list {
     padding: 24px 0;
   }

+ 50 - 18
src/components/Adult/preview/ArticleViewChs/Practicechs.vue

@@ -17,7 +17,10 @@
           :stopAudio="stopAudio"
           :width="555"
           :mp3Source="curQue.mp3_list[0].source"
+          :ed="ed"
+          type="audioLine"
           @handleChangeStopAudio="handleChangeStopAudio"
+          @emptyEd="emptyEd"
         />
       </div>
       <div class="aduioLine-right">
@@ -26,9 +29,13 @@
           @click="changeRepeat"
         ></span>
         <span
-          :class="['pinyin-16', isShowPY ? '' : 'disabled']"
+          :class="['pinyin-16', config.isShowPY ? '' : 'disabled']"
           @click="changePinyin"
         ></span>
+        <span
+          :class="['EN-16', config.isShowEN ? '' : 'disabled']"
+          @click="changeEN"
+        ></span>
       </div>
     </div>
     <template v-if="resObj">
@@ -46,7 +53,10 @@
                 curQue.wordTime &&
                   curQue.wordTime[index] &&
                   curQue.wordTime[index].bg,
-                index
+                index,
+                curQue.wordTime &&
+                  curQue.wordTime[index] &&
+                  curQue.wordTime[index].ed
               )
             "
           >
@@ -67,7 +77,7 @@
                     <span class="NNPE-words-box">
                       <template v-if="curQue.pyPosition == 'top'">
                         <span
-                          v-if="isShowPY"
+                          v-if="config.isShowPY"
                           class="NNPE-pinyin"
                           :class="[
                             pItem.className ? pItem.className : '',
@@ -80,7 +90,7 @@
                       <span
                         class="NNPE-chs"
                         :class="[
-                          pItem.padding && isShowPY ? 'padding' : '',
+                          pItem.padding && config.isShowPY ? 'padding' : '',
                           sentIndex == index ? 'wordBlank' : '',
                         ]"
                       >
@@ -102,7 +112,7 @@
                       </span>
                       <template v-if="curQue.pyPosition == 'bottom'">
                         <span
-                          v-if="isShowPY"
+                          v-if="config.isShowPY"
                           class="NNPE-pinyin"
                           :class="[
                             pItem.className ? pItem.className : '',
@@ -116,7 +126,7 @@
                     <span class="NNPE-words-box">
                       <template v-if="curQue.pyPosition == 'top'">
                         <span
-                          v-if="isShowPY"
+                          v-if="config.isShowPY"
                           :class="[
                             'NNPE-pinyin',
                             sentIndex == index ? 'wordBlank' : '',
@@ -145,7 +155,7 @@
                       </span>
                       <template v-if="curQue.pyPosition == 'bottom'">
                         <span
-                          v-if="isShowPY"
+                          v-if="config.isShowPY"
                           :class="[
                             'NNPE-pinyin',
                             sentIndex == index ? 'wordBlank' : '',
@@ -162,7 +172,7 @@
                   <template v-else>
                     <template v-if="curQue.pyPosition == 'top'">
                       <span
-                        v-if="isShowPY"
+                        v-if="config.isShowPY"
                         class="NNPE-pinyin"
                         :class="[
                           pItem.padding ? 'padding' : '',
@@ -176,7 +186,7 @@
                     <span
                       class="NNPE-chs"
                       :class="[
-                        pItem.padding && isShowPY ? 'padding' : '',
+                        pItem.padding && config.isShowPY ? 'padding' : '',
                         sentIndex == index ? 'wordBlank' : '',
                       ]"
                     >
@@ -200,7 +210,7 @@
                     </span>
                     <template v-if="curQue.pyPosition == 'bottom'">
                       <span
-                        v-if="isShowPY"
+                        v-if="config.isShowPY"
                         class="NNPE-pinyin"
                         :class="[
                           pItem.padding ? 'padding' : '',
@@ -278,6 +288,9 @@
         :noFont="noFont"
         :NNPENewWordList="NNPENewWordList"
         :currentTreeID="currentTreeID"
+        :config="config"
+        @changePinyin="changePinyin"
+        @changeEN="changeEN"
         @exitFullscreen="exitFullscreen"
         @changeIsFull="changeIsFull"
       />
@@ -293,7 +306,14 @@ import AudioCompare from "../AudioCompare.vue";
 import Voicefullscreen from "../Voicefullscreen.vue";
 export default {
   name: "ArticleView",
-  props: ["curQue", "noFont", "themeColor", "NNPENewWordList", "currentTreeID"],
+  props: [
+    "curQue",
+    "noFont",
+    "themeColor",
+    "NNPENewWordList",
+    "currentTreeID",
+    "config",
+  ],
   components: {
     AudioLine,
     Soundrecord,
@@ -308,13 +328,13 @@ export default {
       enFhList: [",", ".", ";", "?", "!", ":", ">", "<"],
       stopAudio: false,
       sentIndex: 0,
-      isShowPY: true,
       isRepeat: false,
       currSent: null, //当前句子的时间
       isRecord: false,
       wavblob: null,
       isFull: false,
       mathNum: Math.random().toString(36).substr(2),
+      ed: undefined,
     };
   },
   computed: {
@@ -338,6 +358,18 @@ export default {
   },
   //方法集合
   methods: {
+    //拼音的显示和隐藏
+    changePinyin() {
+      if (this.config.isHasPY) {
+        this.$emit("changeConfig", "isShowPY");
+      }
+    },
+    // 英文的显示和隐藏
+    changeEN() {
+      if (this.config.isHasEN) {
+        this.$emit("changeConfig", "isShowEN");
+      }
+    },
     pauseAudio() {
       let audio = document.getElementsByTagName("audio");
       audio.forEach((item) => {
@@ -526,17 +558,21 @@ export default {
       return total;
     },
     //点击播放某个句子
-    handleChangeTime(time, index) {
+    handleChangeTime(time, index, ed) {
       let _this = this;
       if (this.isRepeat) {
         _this.currSent = _this.curQue.wordTime[index];
       }
       _this.sentIndex = index;
+      _this.ed = ed;
       if (time) {
         _this.curTime = time;
         _this.$refs.audioLine.onTimeupdateTime(time / 1000, true);
       }
     },
+    emptyEd() {
+      this.ed = undefined;
+    },
     handleWav(data) {},
     // 录音时暂停音频播放
     handleParentPlay() {
@@ -546,10 +582,6 @@ export default {
     handleChangeStopAudio() {
       this.stopAudio = false;
     },
-    //拼音的显示隐藏
-    changePinyin() {
-      this.isShowPY = !this.isShowPY;
-    },
     // 单句是否重复播放
     changeRepeat() {
       let _this = this;
@@ -617,7 +649,7 @@ export default {
       display: flex;
       justify-content: space-between;
       align-items: center;
-      width: 72px;
+      width: 92px;
       height: 40px;
       box-sizing: border-box;
       padding: 0 12px;

+ 98 - 16
src/components/Adult/preview/ArticleViewChs/WordModelChs.vue

@@ -1,19 +1,35 @@
 <!--  -->
 <template>
   <div class="NNPE-ArticleView" v-if="curQue">
-    <div
-      class="aduioLine-box"
-      v-if="
-        curQue.mp3_list && curQue.mp3_list.length > 0 && curQue.mp3_list[0].id
-      "
-    >
-      <AudioLine
-        audioId="artWordAudio"
-        :mp3="curQue.mp3_list[0].id"
-        :getCurTime="getCurTime"
-        :mp3Source="curQue.mp3_list[0].source"
-        ref="audioLine"
-      />
+    <div class="aduioLine-box aduioLine-practice">
+      <div class="aduioLine-content">
+        <template
+          v-if="
+            curQue.mp3_list &&
+            curQue.mp3_list.length > 0 &&
+            curQue.mp3_list[0].id
+          "
+        >
+          <AudioLine
+            audioId="artPhraseAudio"
+            :mp3="curQue.mp3_list[0].id"
+            :getCurTime="getCurTime"
+            :mp3Source="curQue.mp3_list[0].source"
+            :width="590"
+            ref="audioLine"
+          />
+        </template>
+      </div>
+      <div class="aduioLine-right">
+        <span
+          :class="['pinyin-16', config.isShowPY ? '' : 'disabled']"
+          @click="changePinyin"
+        ></span>
+        <span
+          :class="['EN-16', config.isShowEN ? '' : 'disabled']"
+          @click="changeEN"
+        ></span>
+      </div>
     </div>
     <template v-if="resArr.length > 0">
       <div class="NPC-sentences-list">
@@ -42,6 +58,7 @@
                     >
                       <span class="NNPE-words-box">
                         <span
+                          v-if="curQue.pyPosition == 'top' && config.isShowPY"
                           class="NNPE-pinyin"
                           :class="[pItem.className ? pItem.className : '']"
                           >{{ pItem.pinyin }}</span
@@ -63,11 +80,22 @@
                           ]"
                           >{{ pItem.chs }}</span
                         >
+                        <span
+                          v-if="
+                            curQue.pyPosition == 'bottom' && config.isShowPY
+                          "
+                          class="NNPE-pinyin"
+                          :class="[pItem.className ? pItem.className : '']"
+                          >{{ pItem.pinyin }}</span
+                        >
                       </span>
                       <span class="NNPE-words-box">
-                        <span class="NNPE-pinyin" style="text-align: left">{{
-                          item.wordsList[pIndex + 1].pinyin
-                        }}</span>
+                        <span
+                          v-if="curQue.pyPosition == 'top' && config.isShowPY"
+                          class="NNPE-pinyin"
+                          style="text-align: left"
+                          >{{ item.wordsList[pIndex + 1].pinyin }}</span
+                        >
                         <span
                           class="NNPE-chs"
                           style="text-align: left"
@@ -81,10 +109,19 @@
                           ]"
                           >{{ item.wordsList[pIndex + 1].chs }}</span
                         >
+                        <span
+                          v-if="
+                            curQue.pyPosition == 'bottom' && config.isShowPY
+                          "
+                          class="NNPE-pinyin"
+                          style="text-align: left"
+                          >{{ item.wordsList[pIndex + 1].pinyin }}</span
+                        >
                       </span>
                     </template>
                     <template v-else>
                       <span
+                        v-if="curQue.pyPosition == 'top' && config.isShowPY"
                         class="NNPE-pinyin"
                         :class="[
                           pItem.padding ? 'padding' : '',
@@ -105,6 +142,15 @@
                         ]"
                         >{{ pItem.chs }}</span
                       >
+                      <span
+                        v-if="curQue.pyPosition == 'bottom' && config.isShowPY"
+                        class="NNPE-pinyin"
+                        :class="[
+                          pItem.padding ? 'padding' : '',
+                          pItem.className ? pItem.className : '',
+                        ]"
+                        >{{ pItem.pinyin }}</span
+                      >
                     </template>
                   </template>
                 </template>
@@ -152,6 +198,7 @@ export default {
     "NNPENewWordList",
     "themeColor",
     "currentTreeID",
+    "config",
   ],
   components: {
     AudioLine,
@@ -213,6 +260,18 @@ export default {
   },
   //方法集合
   methods: {
+    //拼音的显示和隐藏
+    changePinyin() {
+      if (this.config.isHasPY) {
+        this.$emit("changeConfig", "isShowPY");
+      }
+    },
+    // 英文的显示和隐藏
+    changeEN() {
+      if (this.config.isHasEN) {
+        this.$emit("changeConfig", "isShowEN");
+      }
+    },
     getCurTime(curTime) {
       this.curTime = curTime * 1000;
     },
@@ -401,6 +460,29 @@ export default {
 //@import url(); 引入公共css类
 .NNPE-ArticleView {
   width: 100%;
+  .aduioLine-practice {
+    display: flex;
+    justify-content: flex-start;
+    align-items: center;
+    .aduioLine-content {
+      flex: 1;
+    }
+    .aduioLine-right {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      width: 69px;
+      height: 40px;
+      box-sizing: border-box;
+      padding: 0 12px;
+      border-left: 1px solid rgba(0, 0, 0, 0.1);
+      > span {
+        width: 16px;
+        height: 16px;
+        cursor: pointer;
+      }
+    }
+  }
   .NPC-sentences-list {
     padding: 24px 0;
   }

+ 41 - 0
src/components/Adult/preview/ArticleViewChs/index.vue

@@ -59,6 +59,8 @@
         :noFont="noFont"
         v-if="!showPhrases && !showPractice && !showWord"
         :currentTreeID="currentTreeID"
+        :config="config"
+        @changeConfig="changeConfig"
       />
       <PhraseModel
         :curQue="curQue"
@@ -70,6 +72,8 @@
         :currentTreeID="currentTreeID"
         :bodyLeft="bodyLeft"
         v-if="showPhrases"
+        :config="config"
+        @changeConfig="changeConfig"
       />
       <Practice
         :curQue="curQue"
@@ -80,6 +84,8 @@
         :NNPENewWordList="NNPENewWordList"
         :currentTreeID="currentTreeID"
         v-if="showPractice"
+        :config="config"
+        @changeConfig="changeConfig"
       />
       <WordModel
         :curQue="curQue"
@@ -92,6 +98,8 @@
         :noFont="noFont"
         :currentTreeID="currentTreeID"
         v-if="showWord"
+        :config="config"
+        @changeConfig="changeConfig"
       />
     </div>
   </div>
@@ -119,6 +127,12 @@ export default {
       bodyLeft: 0,
       bodyWidth: 0,
       noFont: ["~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "/"],
+      config: {
+        isShowEN: false,
+        isHasEN: false,
+        isShowPY: false,
+        isHasPY: false,
+      },
     };
   },
   computed: {
@@ -148,6 +162,9 @@ export default {
   },
   //方法集合
   methods: {
+    changeConfig(obj) {
+      this.config[obj] = !this.config[obj];
+    },
     // 处理字体大小
     handleFontsize(symbol) {
       if (symbol == "+") {
@@ -168,6 +185,13 @@ export default {
       this[obj2] = false;
       this.showPreview = false;
     },
+    handleObj(list) {
+      let pinyin = "";
+      list.forEach((item) => {
+        pinyin += item.pinyin;
+      });
+      return pinyin;
+    },
   },
   //生命周期 - 创建完成(可以访问当前this实例)
   created() {},
@@ -178,6 +202,23 @@ export default {
     this.$nextTick(() => {
       this.bodyLeft = this.$refs.ArticleViewbody.getBoundingClientRect().left;
     });
+    for (let i = 0; i < this.curQue.detail.length; i++) {
+      let enStr = this.curQue.detail[i].sentencesEn
+        ? this.curQue.detail[i].sentencesEn.join("")
+        : "";
+      if (enStr) {
+        this.config.isShowEN = true;
+        this.config.isHasEN = true;
+      }
+      let pinyin = this.handleObj(this.curQue.detail[i].wordsList);
+      if (pinyin) {
+        this.config.isShowPY = true;
+        this.config.isHasPY = true;
+      }
+      if (enStr && pinyin) {
+        break;
+      }
+    }
   },
   beforeCreate() {}, //生命周期 - 创建之前
   beforeMount() {}, //生命周期 - 挂载之前

+ 3 - 1
src/components/Adult/preview/NewWordShow.vue

@@ -234,8 +234,9 @@ export default {
       this.isPraShow = true;
     },
     closeifFreeShow(data, rowIndex, colIndex) {
-      this.curQue.option[rowIndex].imgarr[colIndex-1] = data;
+      this.curQue.option[rowIndex].imgarr[colIndex - 1] = data;
       this.ifFreeShow = false;
+      this.freeWrite(data, rowIndex, colIndex);
       this.$forceUpdate();
     },
     freeWrite(imgUrl, index, indexs) {
@@ -244,6 +245,7 @@ export default {
       this.activeColIndex = indexs;
       this.currentHz = this.curQue.option[index].con;
       this.currenHzData = imgUrl;
+      console.log(this.currenHzData);
     },
   },
   //生命周期 - 创建完成(可以访问当前this实例)

+ 50 - 51
src/components/Adult/preview/components/FreewriteLettle.vue

@@ -16,27 +16,6 @@
     />
     <div class="right-content">
       <div class="right-strockred">
-        <!-- <Freewrite
-          :cur="cur"
-          :lineColor="hanzicolor"
-          :lineWidth="hanziweight"
-          :themeColor="themeColor"
-          ref="freewrite"
-        /> -->
-        <!-- <div
-          v-if="data.history"
-          @click.stop="play"
-          :class="[
-            'strock-play-box',
-            themeColor == 'green'
-              ? 'green-border'
-              : themeColor == 'red'
-              ? 'red-border'
-              : themeColor == 'brown'
-              ? 'brown-border'
-              : 'red-border',
-          ]"
-        ></div> -->
         <template v-if="!hasPlay && data.strokes_image_url">
           <img class="img" :src="data.strokes_image_url" alt="" />
         </template>
@@ -51,9 +30,12 @@
           ref="esign"
           id="esign"
         />
+        <a @click="resetHuahua" class="clean-btn"></a>
       </div>
       <ul class="nav-list">
-        <li @click="resetHuahua()">播放</li>
+        <li @click="play()" :class="currenHzData.history ? '' : 'disabled'">
+          播放
+        </li>
         <li @click="handleWriteImg">保存</li>
       </ul>
     </div>
@@ -119,34 +101,32 @@ export default {
   methods: {
     play(index) {
       let _this = this;
-      if (this.hasPlay) {
-        this.$message.warning("请等待播放完成");
-        return;
-      }
-      this.$refs.esign.reset();
-      this.hasPlay = true;
-      let c = document.getElementById("esign");
-      let cxt = document.getElementById("esign").getContext("2d");
-      cxt.clearRect(0, 0, c.width, c.height);
-      let history = null;
-      console.log(_this.$refs.esign.history);
-      history =
-        _this.$refs.esign.history.length > 0
-          ? _this.$refs.esign.history
-          : _this.currenHzData.history;
-      const len = history.length;
-      let i = 0;
-      const runner = () => {
-        i++;
-        if (i < len) {
-          _this.$refs.esign.draw(null, history[i][0], history[i][1]);
-          requestAnimationFrame(runner);
-        } else {
-          console.log("播放完成");
-          _this.hasPlay = false;
+      if (this.currenHzData.history) {
+        if (this.hasPlay) {
+          this.$message.warning("请等待播放完成");
+          return;
         }
-      };
-      requestAnimationFrame(runner);
+        this.$refs.esign.reset();
+        this.hasPlay = true;
+        let c = document.getElementById("esign");
+        let cxt = document.getElementById("esign").getContext("2d");
+        cxt.clearRect(0, 0, c.width, c.height);
+        let history = null;
+        history = _this.currenHzData.history;
+        const len = history.length;
+        let i = 0;
+        const runner = () => {
+          i++;
+          if (i < len) {
+            _this.$refs.esign.draw(null, history[i][0], history[i][1]);
+            requestAnimationFrame(runner);
+          } else {
+            console.log("播放完成");
+            _this.hasPlay = false;
+          }
+        };
+        requestAnimationFrame(runner);
+      }
     },
 
     changeNav(index) {
@@ -209,7 +189,7 @@ export default {
   },
   //生命周期 - 创建完成(可以访问当前this实例)
   created() {
-    // console.log(this.cur);
+    console.log(this.currenHzData);
     let _this = this;
     let color = _this.colorsList[_this.colorIndex];
     _this.hanzicolor = color;
@@ -240,6 +220,9 @@ export default {
   border-radius: 8px;
   position: relative;
   .clean-btn {
+    position: absolute;
+    right: 8px;
+    bottom: 8px;
     width: 16px;
     height: 16px;
     margin: 0 4px;
@@ -289,7 +272,7 @@ export default {
     background: #f3f3f3;
     border-radius: 16px;
     box-sizing: border-box;
-    padding: 30px 16px;
+    padding: 30px 16px 30px;
     display: flex;
     flex-direction: column;
     justify-content: flex-start;
@@ -322,6 +305,13 @@ export default {
         &:active {
           background: #c43c3c;
         }
+        &.disabled {
+          color: #fff;
+          background-color: #c8c9cc;
+          border-color: #c8c9cc;
+          cursor: not-allowed;
+          background-image: none;
+        }
       }
     }
     .right-strockred {
@@ -331,6 +321,8 @@ export default {
         no-repeat;
       background-size: 100% 100%;
       position: relative;
+      border-radius: 8px;
+      overflow: hidden;
       .img {
         position: absolute;
       }
@@ -509,6 +501,13 @@ export default {
           &:active {
             background: #1fa189;
           }
+          &.disabled {
+            color: #fff;
+            background-color: #c8c9cc;
+            border-color: #c8c9cc;
+            cursor: not-allowed;
+            background-image: none;
+          }
         }
       }
     }

+ 1 - 1
src/components/Adult/preview/components/Notecard.vue

@@ -6,7 +6,7 @@
     </div>
     <div class="NPC-notes">
       <div class="NPC-notes-con">
-        <!-- <span class="NPC-notes-con-number">{{ item.number }}</span> -->
+        <span class="NPC-notes-con-number">{{ item.number }}</span>
         <span class="NPC-notes-con-text">{{ item.con }}</span>
       </div>
       <div class="NPC-notes-trans">

+ 58 - 7
src/components/Adult/preview/components/Practice.vue

@@ -43,8 +43,8 @@
               </div>
             </div>
             <div class="footer">
-              <div @click="collectFlag = !collectFlag" class="bg-box">
-                <template v-if="collectFlag">
+              <div @click="handleColl" class="bg-box">
+                <template v-if="collFlag">
                   <img
                     :src="
                       themeColor
@@ -72,7 +72,7 @@
                     class="practice-icon"
                   />
                 </template>
-                收藏
+                {{ collFlag ? "已收藏" : "收藏" }}
               </div>
             </div>
           </div>
@@ -133,8 +133,8 @@
             </div>
             <div class="left-content-pra"></div>
             <div class="footer">
-              <div @click="collectFlag = !collectFlag" class="bg-box">
-                <template v-if="collectFlag">
+              <div class="bg-box" @click="handleColl">
+                <template v-if="collFlag">
                   <img
                     :src="
                       themeColor
@@ -162,7 +162,7 @@
                     class="practice-icon"
                   />
                 </template>
-                收藏
+                {{ collFlag ? "已收藏" : "收藏" }}
               </div>
             </div>
           </div>
@@ -222,6 +222,8 @@ import Strockred from "./Strockred.vue";
 import Freewrite from "./Freewrite.vue";
 import Audio from "./AudioRed.vue";
 
+import { LearnWebSI } from "../../../../api/ajax";
+
 export default {
   components: {
     Strockplayredline,
@@ -245,14 +247,63 @@ export default {
       thinpenActive: require("../../../../assets/common/thin-pen-active.png"),
       thickpen: require("../../../../assets/common/thick-pen.png"),
       thickpenActive: require("../../../../assets/common/thick-pen-active.png"),
-      collectFlag: false, // 是否收藏
       isShow: 0,
+      collFlag: false,
     };
   },
   computed: {},
   watch: {},
   //方法集合
   methods: {
+    handleColl() {
+      let _this = this;
+      if (_this.collFlag) {
+        _this.cancleColl();
+      } else {
+        _this.addColl();
+      }
+    },
+    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("收藏成功!");
+      });
+    },
+    //取消收藏
+    cancleColl() {
+      let MethodName = "order-collection_manager-CancelMyGoodsCollection_WS";
+      let data = {
+        goods_type: 501,
+        goods_list: [
+          {
+            goods_id: this.currentTreeID, //课件的id
+            new_word: this.word.detail.new_word,
+          },
+        ],
+      };
+      LearnWebSI(MethodName, data).then((res) => {
+        this.collFlag = false;
+        this.$message.success("取消成功!");
+      });
+    },
     changeNav(index) {
       let _this = this;
       _this.navIndex = index;

+ 2 - 2
src/components/Adult/preview/components/Strockplayredline.vue

@@ -115,8 +115,8 @@ export default {
 }
 .strock-play-box {
   position: absolute;
-  // right: -2px;
-  // top: 0px;
+  right: -2px;
+  top: 0px;
   z-index: 999;
   width: 22px !important;
   height: 22px !important;

+ 2 - 2
vue.config.js

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