guanchunjie преди 3 години
родител
ревизия
6915b612f5
променени са 20 файла, в които са добавени 2652 реда и са изтрити 183 реда
  1. 12 2
      src/components/Adult/Preview.vue
  2. 14 9
      src/components/Adult/inputModules/ArticleTemChs/components/ClauseresultChs.vue
  3. 35 42
      src/components/Adult/inputModules/ArticleTemChs/components/ParagraphChs.vue
  4. 4 4
      src/components/Adult/inputModules/DialogueArticleChs/components/ArticleChs.vue
  5. 28 12
      src/components/Adult/inputModules/DialogueArticleChs/components/ClauseresultChs.vue
  6. 130 41
      src/components/Adult/inputModules/DialogueArticleChs/components/ParagraphChs.vue
  7. 83 44
      src/components/Adult/inputModules/DialogueArticleChs/index.vue
  8. 75 13
      src/components/Adult/preview/ArticleViewChs/NormalModelChs.vue
  9. 7 6
      src/components/Adult/preview/ArticleViewChs/PhraseModelChs.vue
  10. 22 8
      src/components/Adult/preview/ArticleViewChs/WordModelChs.vue
  11. 7 1
      src/components/Adult/preview/ArticleViewChs/index.vue
  12. 422 0
      src/components/Adult/preview/DialogueArticleViewChs/NormalModelChs.vue
  13. 451 0
      src/components/Adult/preview/DialogueArticleViewChs/PhraseModelChs.vue
  14. 475 0
      src/components/Adult/preview/DialogueArticleViewChs/Practicechs.vue
  15. 74 0
      src/components/Adult/preview/DialogueArticleViewChs/RemarkChs.vue
  16. 103 0
      src/components/Adult/preview/DialogueArticleViewChs/RoleChs.vue
  17. 458 0
      src/components/Adult/preview/DialogueArticleViewChs/WordModelChs.vue
  18. 243 0
      src/components/Adult/preview/DialogueArticleViewChs/index.vue
  19. 7 0
      src/styles/index.scss
  20. 2 1
      src/views/adultInput.vue

+ 12 - 2
src/components/Adult/Preview.vue

@@ -58,6 +58,14 @@
                     :NNPEAnnotationList="NNPEAnnotationList"
                   />
                 </template>
+                <template v-if="itemss.data.type == 'dialogue_article_chs'">
+                  <DialogueArticleViewChs
+                    :curQue="itemss.data"
+                    :NNPENewWordList="NNPENewWordList"
+                    :NNPENewPhraseList="NNPENewPhraseList"
+                    :NNPEAnnotationList="NNPEAnnotationList"
+                  />
+                </template>
                 <template v-if="itemss.data.type == 'sentence_segword_chs'">
                   <SentenceSegWordViewChs :curQue="itemss.data" />
                 </template>
@@ -87,6 +95,7 @@ import Picture from "./preview/Picture.vue"; // 图片模板
 import Record from "./preview/Record.vue"; // 音频播放
 import Soundrecord from "./preview/Soundrecord.vue"; // 录音模板
 import ArticleTemChs from "./preview/ArticleViewChs/index.vue"; // 文章模板
+import DialogueArticleViewChs from "./preview/DialogueArticleViewChs/index.vue"; // 文章模板
 import SentenceSegWordViewChs from "./preview/SentenceSegWordViewChs.vue"; //句子分词
 import WordPhrase from "./preview/WordPhrase.vue"; // 生词 短语
 import Notes from "./preview/Notes.vue"; // 注释
@@ -94,7 +103,7 @@ import Ligature from "./preview/Ligature.vue";
 import InputHasRecord from "./preview/InputHasRecord.vue"; // 输入加录音
 import TextInputRecord from "./preview/TextInputRecord.vue"; // 文本+输入+录音
 import SentenceInput from "./preview/SentenceInput.vue"; // 输入选项
-import NumberSelectHasRecord from "./preview/NumberSelectHasRecord.vue" // 数字组合
+import NumberSelectHasRecord from "./preview/NumberSelectHasRecord.vue"; // 数字组合
 export default {
   name: "preview",
   components: {
@@ -102,6 +111,7 @@ export default {
     Record,
     Soundrecord,
     ArticleTemChs,
+    DialogueArticleViewChs,
     SentenceSegWordViewChs,
     WordPhrase,
     Notes,
@@ -172,7 +182,7 @@ export default {
         }
       }
     },
-   
+
     // 上一页
     handleNNPEprev() {
       const _this = this;

+ 14 - 9
src/components/Adult/inputModules/ArticleTemChs/components/ClauseresultChs.vue

@@ -17,13 +17,17 @@
           placeholder="请输入内容"
           v-model="item.para"
           :readonly="item.isReadonly"
-          @change="handleChange"
+          @change="handleChange(item.para, index)"
           @blur="onBlur(item, 'para')"
         ></el-input>
-        <el-button type="danger" size="small" @click="editClause(item)"
+        <el-button
+          v-if="item.isReadonly"
+          type="danger"
+          size="small"
+          @click="editClause(item)"
           >编辑</el-button
         >
-        <el-button type="primary" size="small" @click="sureClause(index)"
+        <el-button v-else type="primary" size="small" @click="sureClause(index)"
           >生词分词</el-button
         >
       </template>
@@ -65,21 +69,22 @@ export default {
         let para = item.sentences.join("\n");
         let obj = {
           para: para,
-          isReadonly: true,
+          isReadonly: false,
         };
         paraList.push(obj);
       });
       this.para_list = paraList;
     },
     //input内容变化
-    handleChange(value) {
-      // console.log(value);
-      // let arr = value.split("\n");
-      // console.log(arr);
+    handleChange(value, index) {
+      let _this = this;
+      let sentArr = value.split("\n");
+      this.$set(_this.curQue.detail[index], "sentences", sentArr);
     },
     sureClause(index) {
       let _this = this;
-      let paraStr = _this.para_list[index].para.replace(/\n/g, "");
+      let para_list = JSON.parse(JSON.stringify(_this.para_list));
+      let paraStr = para_list[index].para.replace(/\n/g, "");
       let orgPara = _this.curQue.detail[index].para;
       if (paraStr != orgPara) {
         this.$message.warning("跟上面的段落内容不一致,请检查!");

+ 35 - 42
src/components/Adult/inputModules/ArticleTemChs/components/ParagraphChs.vue

@@ -1,49 +1,42 @@
 <!--分句组件-->
 <template>
   <div class="Big-Book-Maxwidth">
-    <div class="Big-Book-content m">
-      <div class="Big-Book-main">
-        <div class="Big-Book-con">
-          <div class="Big-Book-con-top">
-            <span class="Big-Book-left-text">文章段落:</span>
-            <el-button
-              type="text"
-              size="small"
-              @click="editPara"
-              v-if="readonly"
-              >编辑段落</el-button
-            >
-          </div>
-          <div
-            class="NPC-para-list"
-            v-for="(item, index) in curQue.detail"
-            :key="'para' + index"
-          >
-            <span class="NPC-para-number">{{ index + 1 }}.</span>
-            <el-input
-            style="width: 82%;"
-              type="textarea"
-              :autosize="{ minRows: 3 }"
-              placeholder="请输入内容"
-              v-model="item.para"
-              @blur="onBlur(item, 'para')"
-              :readonly="readonly"
-            ></el-input>
-            <template v-if="index == 0">
-              <el-checkbox v-model="item.isTitle">文章标题</el-checkbox>
-            </template>
-            <img
-              @click="deleteOption(index)"
-              class="close"
-              src="../../../../../assets/adult/del-close.png"
-              alt=""
-              v-if="!readonly"
-            />
-          </div>
-            <el-button type="primary" size="small" @click="sureSegResult">确定分句</el-button>
-          </div>
-        </div>
+    <div class="Big-Book-con">
+      <div class="Big-Book-con-top">
+        <span class="Big-Book-left-text">文章段落:</span>
+        <el-button type="text" size="small" @click="editPara" v-if="readonly"
+          >编辑段落</el-button
+        >
       </div>
+      <div
+        class="NPC-para-list"
+        v-for="(item, index) in curQue.detail"
+        :key="'para' + index"
+      >
+        <span class="NPC-para-number">{{ index + 1 }}.</span>
+        <el-input
+          style="width: 82%"
+          type="textarea"
+          :autosize="{ minRows: 3 }"
+          placeholder="请输入内容"
+          v-model="item.para"
+          @blur="onBlur(item, 'para')"
+          :readonly="readonly"
+        ></el-input>
+        <template v-if="index == 0">
+          <el-checkbox v-model="item.isTitle">文章标题</el-checkbox>
+        </template>
+        <img
+          @click="deleteOption(index)"
+          class="close"
+          src="../../../../../assets/adult/del-close.png"
+          alt=""
+          v-if="!readonly"
+        />
+      </div>
+      <el-button type="primary" size="small" @click="sureSegResult"
+        >确定分句</el-button
+      >
     </div>
   </div>
 </template>

+ 4 - 4
src/components/Adult/inputModules/DialogueArticleChs/components/ArticleChs.vue

@@ -1,17 +1,16 @@
 <!--  -->
 <template>
   <div class="NPC-Dialogue-article" v-if="curQue">
-    <span class="Big-Book-left-text">文章:</span>
+    <span class="adult-book-lable-bottom">文章:</span>
     <el-input
-      style="width: 85%"
-      class="NPC-Dialogue-input"
+      class="adult-book-input-800"
       type="textarea"
       :autosize="{ minRows: 10 }"
       placeholder="请输入文章"
       v-model="curQue.article"
       @blur="onBlur(curQue, 'article')"
     ></el-input>
-    <div>
+    <div style="margin-top: 10px">
       <el-button type="primary" size="small" @click="createPara"
         >生成段落</el-button
       >
@@ -26,6 +25,7 @@ export default {
   data() {
     return {
       detailItem: {
+        roleIndex: "",
         paraIndex: 0,
         para: "",
         sentences: [],

+ 28 - 12
src/components/Adult/inputModules/DialogueArticleChs/components/ClauseresultChs.vue

@@ -2,7 +2,7 @@
 <template>
   <div class="Big-Book-Maxwidth">
     <div class="Big-Book-con-top">
-      <span class="Big-Book-left-text">分句结果:</span>
+      <span class="adult-book-lable-bottom">分句结果:</span>
     </div>
     <div
       class="NPC-sentence-list"
@@ -11,19 +11,23 @@
     >
       <template v-if="item.para">
         <el-input
-          style="width: 85%;white-space:nowrap;"
+          class="adult-book-input-800"
           type="textarea"
           :autosize="{ minRows: 3 }"
           placeholder="请输入内容"
           v-model="item.para"
           :readonly="item.isReadonly"
-          @change="handleChange"
+          @change="handleChange(item.para, index)"
           @blur="onBlur(item, 'para')"
         ></el-input>
-        <el-button type="danger" size="small" @click="editClause(item)"
+        <el-button
+          v-if="item.isReadonly"
+          type="danger"
+          size="small"
+          @click="editClause(item)"
           >编辑</el-button
         >
-        <el-button type="primary" size="small" @click="sureClause(index)"
+        <el-button v-else type="primary" size="small" @click="sureClause(index)"
           >生词分词</el-button
         >
       </template>
@@ -42,6 +46,7 @@ export default {
   data() {
     return {
       para_list: [],
+      paraIndex: "",
     };
   },
   computed: {},
@@ -65,27 +70,32 @@ export default {
         let para = item.sentences.join("\n");
         let obj = {
           para: para,
-          isReadonly: true,
+          isReadonly: false,
         };
         paraList.push(obj);
       });
       this.para_list = paraList;
+      if (this.paraIndex !== "") {
+        this.para_list[this.paraIndex].isReadonly = true;
+      }
     },
     //input内容变化
-    handleChange(value) {
-      // console.log(value);
-      // let arr = value.split("\n");
-      // console.log(arr);
+    handleChange(value, index) {
+      let _this = this;
+      let sentArr = value.split("\n");
+      this.$set(_this.curQue.detail[index], "sentences", sentArr);
     },
     sureClause(index) {
+      debugger;
       let _this = this;
-      let paraStr = _this.para_list[index].para.replace(/\n/g, "");
+      let para_list = JSON.parse(JSON.stringify(_this.para_list));
+      let paraStr = para_list[index].para.replace(/\n/g, "");
       let orgPara = _this.curQue.detail[index].para;
       if (paraStr != orgPara) {
         this.$message.warning("跟上面的段落内容不一致,请检查!");
         return;
       }
-      _this.para_list[index].isReadonly = true;
+      this.paraIndex = index;
       let sentArr = _this.para_list[index].para.split("\n");
       _this.$set(_this.curQue.detail[index], "sentences", sentArr);
       _this.segByWord(_this.curQue.detail[index].sentences, index);
@@ -93,6 +103,12 @@ export default {
     editClause(item) {
       item.isReadonly = false;
     },
+    saveClause(item, index) {
+      let _this = this;
+      item.isReadonly = true;
+      let sentArr = item.para.split("\n");
+      _this.$set(_this.curQue.detail[index], "sentences", sentArr);
+    },
     oneClickResult() {},
   },
   //生命周期 - 创建完成(可以访问当前this实例)

+ 130 - 41
src/components/Adult/inputModules/DialogueArticleChs/components/ParagraphChs.vue

@@ -1,50 +1,89 @@
 <!--分句组件-->
 <template>
   <div class="Big-Book-Maxwidth">
-    <div class="Big-Book-content m">
-      <div class="Big-Book-main">
-        <div class="Big-Book-con">
-          <div class="Big-Book-con-top">
-            <span class="Big-Book-left-text">文章段落:</span>
-            <el-button
-              type="text"
-              size="small"
-              @click="editPara"
-              v-if="readonly"
-              >编辑段落</el-button
-            >
-          </div>
-          <div
-            class="NPC-para-list"
-            v-for="(item, index) in curQue.detail"
-            :key="'para' + index"
+    <div class="Big-Book-con">
+      <div class="Big-Book-con-top">
+        <span class="Big-Book-left-text">文章段落:</span>
+        <el-button type="text" size="small" @click="editPara" v-if="readonly"
+          >编辑段落</el-button
+        >
+      </div>
+      <div
+        class="NPC-para-list"
+        v-for="(item, index) in curQue.detail"
+        :key="'para' + index"
+      >
+        <span class="NPC-para-number">{{ index + 1 }}.</span>
+        <el-select
+          v-model="item.roleIndex"
+          placeholder="请选择角色"
+          style="width:120px;margin-right:10px;font-size;12px;"
+        >
+          <el-option
+            v-for="(rItem, rIndex) in roleList"
+            :key="'role' + index + rIndex"
+            :label="rItem.label"
+            :value="rItem.id"
           >
-            <span class="NPC-para-number">{{ index + 1 }}.</span>
-            <el-input
-            style="width: 82%;"
-              type="textarea"
-              :autosize="{ minRows: 3 }"
-              placeholder="请输入内容"
-              v-model="item.para"
-              @blur="onBlur(item, 'para')"
-              :readonly="readonly"
-            ></el-input>
-            <template v-if="index == 0">
-              <el-checkbox v-model="item.isTitle">文章标题</el-checkbox>
-            </template>
-            <img
-              @click="deleteOption(index)"
-              class="close"
-              src="../../../../../assets/adult/del-close.png"
-              alt=""
-              v-if="!readonly"
-            />
-          </div>
-            <el-button type="primary" size="small" @click="sureSegResult">确定分句</el-button>
-          </div>
-        </div>
+          </el-option>
+        </el-select>
+        <el-input
+          style="width: 500px"
+          type="textarea"
+          :autosize="{ minRows: 3 }"
+          placeholder="请输入内容"
+          v-model="item.para"
+          @blur="onBlur(item, 'para')"
+          :readonly="readonly"
+        ></el-input>
+        <el-button
+          size="small"
+          type="warning"
+          @click="addRemark(item, index)"
+          >{{ item.remark ? "修改备注" : "添加备注" }}</el-button
+        >
+        <img
+          @click="deleteOption(index)"
+          class="close"
+          src="../../../../../assets/adult/del-close.png"
+          alt=""
+          v-if="!readonly"
+        />
       </div>
+      <el-button type="primary" size="small" @click="sureSegResult"
+        >确定分句</el-button
+      >
     </div>
+    <el-dialog title="标注" :visible.sync="remarkVisible" width="50%">
+      <div class="remark" v-if="remark">
+        <div class="adult-book-input-item">
+          <span class="adult-book-lable">中文:</span>
+          <el-input
+            class="adult-book-input"
+            type="textarea"
+            :autosize="{ minRows: 2 }"
+            placeholder="请输入中文"
+            v-model="remark.chs"
+            @blur="onBlur(remark, 'chs')"
+          ></el-input>
+        </div>
+        <div class="adult-book-input-item">
+          <span class="adult-book-lable">英文:</span>
+          <el-input
+            class="adult-book-input"
+            type="textarea"
+            :autosize="{ minRows: 2 }"
+            placeholder="请输入英文"
+            v-model="remark.en"
+            @blur="onBlur(remark, 'en')"
+          ></el-input>
+        </div>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="remarkVisible = false">取 消</el-button>
+        <el-button type="primary" @click="saveRemark">保 存</el-button>
+      </span>
+    </el-dialog>
   </div>
 </template>
 
@@ -63,6 +102,10 @@ export default {
         mp3_list: [],
       },
       readonly: false,
+      roleList: [],
+      remarkVisible: false,
+      remark: null,
+      paraIndex: 0,
     };
   },
   computed: {},
@@ -70,6 +113,14 @@ export default {
     isClause(newVal, oldVal) {
       this.readonly = newVal;
     },
+    "curQue.roleList": {
+      handler: function (newVal, oldVal) {
+        if (newVal.length > 0) {
+          this.initRoleList();
+        }
+      },
+      deep: true,
+    },
   },
   //方法集合
   methods: {
@@ -85,6 +136,21 @@ export default {
       _this.readonly = true;
       _this.sureSeg();
     },
+    initRoleList() {
+      let roleList = JSON.parse(JSON.stringify(this.curQue.roleList));
+      roleList = roleList.map((item) => {
+        if (item.detail.fullName) {
+          item.label = item.detail.fullName;
+        } else if (item.role) {
+          item.label = item.role;
+        } else if (item.img_list.length > 0) {
+          item.label = "头像" + (item.id + 1);
+        }
+        return item;
+      });
+      this.roleList = roleList;
+      console.log(this.roleList);
+    },
     // 点击生成拼音
     getPinyin(item) {
       console.log(12356);
@@ -140,12 +206,35 @@ export default {
         })
         .catch(() => {});
     },
+    addRemark(item, index) {
+      this.paraIndex = index;
+      if (!item.remark) {
+        item.remark = {
+          chs: "",
+          en: "",
+        };
+      }
+      this.remark = JSON.parse(JSON.stringify(item.remark));
+      console.log(this.remark);
+      this.remarkVisible = true;
+    },
+    saveRemark() {
+      let _this = this;
+      _this.curQue.detail[_this.paraIndex].remark = JSON.parse(
+        JSON.stringify(this.remark)
+      );
+      this.remarkVisible = false;
+      console.log(_this.curQue.detail);
+    },
   },
   //生命周期 - 创建完成(可以访问当前this实例)
   created() {},
   //生命周期 - 挂载完成(可以访问DOM元素)
   mounted() {
     this.readonly = this.isClause;
+    if (this.curQue) {
+      this.initRoleList();
+    }
   },
   beforeCreate() {}, //生命周期 - 创建之前
   beforeMount() {}, //生命周期 - 挂载之前

+ 83 - 44
src/components/Adult/inputModules/DialogueArticleChs/index.vue

@@ -56,20 +56,23 @@
           v-for="(rItem, rIndex) in curQue.roleList"
           :key="'roleList' + rIndex"
         >
-          <span v-if="rItem.role" class="adult-book-input-roleText">{{
-            rItem.role
-          }}</span>
-          <img
-            v-else
-            :src="rItem.img_list[0] && rItem.img_list[0].url"
-            class="adult-book-input-roleImg"
-          />
-          <div class="adult-book-input-fullName">
-            <span class="pinyin">{{
-              rItem.detail.wordsList | handlePinyin
+          <div class="rItem" @click="editRole(rItem)">
+            <span v-if="rItem.role" class="adult-book-input-roleText">{{
+              rItem.role
             }}</span>
-            <span class="chs">{{ rItem.detail.wordsList | handleChs }}</span>
+            <img
+              v-else
+              :src="rItem.img_list[0] && rItem.img_list[0].url"
+              class="adult-book-input-roleImg"
+            />
+            <template v-if="rItem.detail.wordsList.length > 0">
+              <span class="pinyin">{{
+                rItem.detail.wordsList | handlePinyin
+              }}</span>
+              <span class="chs">{{ rItem.detail.wordsList | handleChs }}</span>
+            </template>
           </div>
+          <i class="el-icon-circle-close" @click="delRole(rIndex)"></i>
         </li>
       </ul>
       <el-button type="primary" @click="addRole">添加角色</el-button>
@@ -85,7 +88,7 @@
       <Paragraph :curQue="curQue" :isClause="isClause" :sureSeg="sureSeg" />
     </div>
     <div class="NPC-Book-model">
-      <span class="Big-Book-left-text">拼音位置</span>
+      <span class="adult-book-input-lable">拼音位置:</span>
       <el-radio-group v-model="curQue.pyPosition">
         <el-radio :label="'top'">字上面</el-radio>
         <el-radio :label="'bottom'">字下面</el-radio>
@@ -120,11 +123,20 @@
         <el-button type="primary" @click="saveTimeList">保 存</el-button>
       </span>
     </el-dialog>
-    <el-dialog title="添加角色" :visible.sync="roleVisible" width="60%">
-      <RoleChs
-        ref="createRolelist"
-        :curRole="curQue.roleList[curQue.roleList.length - 1]"
-      />
+    <el-dialog
+      :title="roleStatus == 1 ? '添加角色' : '编辑角色'"
+      :visible.sync="roleVisible"
+      width="60%"
+    >
+      <template v-if="roleStatus == 1">
+        <RoleChs
+          ref="createRolelist"
+          :curRole="curQue.roleList[curQue.roleList.length - 1]"
+        />
+      </template>
+      <template v-else>
+        <RoleChs ref="createRolelist" :curRole="curRole" />
+      </template>
       <span slot="footer" class="dialog-footer">
         <el-button @click="roleVisible = false">取 消</el-button>
         <el-button type="primary" @click="saveRoleList">保 存</el-button>
@@ -196,6 +208,8 @@ export default {
       paraIndex: 0, //段落索引
       cTVisible: false,
       roleVisible: false,
+      roleStatus: 1, //1添加;2是编辑
+      curRole: null,
       loading: false,
       segList: null,
 
@@ -3046,7 +3060,9 @@ export default {
     //添加角色
     addRole() {
       this.roleVisible = true;
+      this.roleStatus = 1;
       let roleCon = {
+        id: this.curQue.roleList.length,
         role: "",
         img_list: [],
         detail: {
@@ -3063,6 +3079,16 @@ export default {
       this.$message.success("保存成功!");
       console.log(this.curQue);
     },
+    //删除角色
+    delRole(index) {
+      this.curQue.roleList.splice(index, 1);
+    },
+    //点击角色
+    editRole(item) {
+      this.roleVisible = true;
+      this.roleStatus = 2;
+      this.curRole = item;
+    },
     changeIsPara() {
       this.isPara = true;
     },
@@ -3206,40 +3232,53 @@ p {
 .adult-book-input-role {
   clear: both;
   overflow: hidden;
+
   > li {
     float: left;
     display: flex;
     justify-content: flex-start;
     align-items: center;
-    .adult-book-input {
-      &-roleText {
-        width: 40px;
-        height: 40px;
-        background: #a7a7a7;
-        border-radius: 100%;
-        text-align: center;
-        line-height: 40px;
-      }
-      &-roleImg {
-        width: 40px;
-        height: 40px;
-      }
-      &-fullName {
-        margin-left: 8px;
-        .pinyin {
-          font-family: "GB-PINYINOK-B";
-          font-size: 14px;
-          line-height: 22px;
-          color: rgba(0, 0, 0, 0.85);
-          margin-right: 8px;
+    padding: 4px 8px;
+    border: 1px #a7a7a7 solid;
+    border-radius: 8px;
+    margin: 0 10px 10px 0px;
+    .rItem {
+      display: flex;
+      justify-content: flex-start;
+      align-items: center;
+
+      .adult-book-input {
+        &-roleText {
+          width: 40px;
+          height: 40px;
+          background: #a7a7a7;
+          border-radius: 100%;
+          text-align: center;
+          line-height: 40px;
         }
-        .chs {
-          font-family: "FZJCGFKTK";
-          font-size: 16px;
-          line-height: 24;
-          color: #000000;
+        &-roleImg {
+          width: 40px;
+          height: 40px;
         }
       }
+      .pinyin {
+        font-family: "GB-PINYINOK-B";
+        font-size: 14px;
+        line-height: 22px;
+        color: rgba(0, 0, 0, 0.85);
+        margin-right: 8px;
+        margin-left: 8px;
+      }
+      .chs {
+        font-family: "FZJCGFKTK";
+        font-size: 16px;
+        line-height: 24px;
+        color: #000000;
+        margin-right: 16px;
+      }
+    }
+    > i {
+      cursor: pointer;
     }
   }
 }

+ 75 - 13
src/components/Adult/preview/ArticleViewChs/NormalModelChs.vue

@@ -1,11 +1,13 @@
 <!--  -->
 <template>
   <div class="NNPE-ArticleView" v-if="curQue">
-    <AudioLine
-      :mp3="curQue.mp3_list[0].url"
-      :getCurTime="getCurTime"
-      ref="audioLine"
-    />
+    <div class="aduioLine-box">
+      <AudioLine
+        :mp3="curQue.mp3_list[0].url"
+        :getCurTime="getCurTime"
+        ref="audioLine"
+      />
+    </div>
     <template v-if="resArr.length > 0">
       <div class="NPC-sentences-list">
         <div
@@ -22,6 +24,8 @@
                 :key="'wordsList' + pIndex"
                 :class="[pItem.wordIndex == 0 ? 'textLeft' : 'textCenter']"
                 @click="handleChangeTime(item.timeList[pItem.sentIndex].bg)"
+                @mouseover="handleMouseover(pItem)"
+                @mouseleave="handleMouseleave"
               >
                 <template v-if="!pItem.width">
                   <template v-if="pItem.isShow">
@@ -44,6 +48,17 @@
                             curTime <= item.timeList[pItem.sentIndex].ed
                               ? 'active'
                               : '',
+                            pItem.paraIndex == paraIndex &&
+                            pItem.sentIndex == sentIndex
+                              ? 'overActive'
+                              : '',
+                            curTime >=
+                              item.timeList[pItem.sentIndex].wordsResultList[
+                                pItem.wordIndex
+                              ].wordBg &&
+                            curTime <= item.timeList[pItem.sentIndex].ed
+                              ? 'wordActive'
+                              : '',
                           ]"
                           >{{ pItem.chs }}</span
                         >
@@ -60,6 +75,17 @@
                             curTime <= item.timeList[pItem.sentIndex].ed
                               ? 'active'
                               : '',
+                            pItem.paraIndex == paraIndex &&
+                            pItem.sentIndex == sentIndex
+                              ? 'overActive'
+                              : '',
+                            curTime >=
+                              item.timeList[pItem.sentIndex].wordsResultList[
+                                pItem.wordIndex
+                              ].wordBg &&
+                            curTime <= item.timeList[pItem.sentIndex].ed
+                              ? 'wordActive'
+                              : '',
                           ]"
                           >{{ item.wordsList[pIndex + 1].chs }}</span
                         >
@@ -82,6 +108,17 @@
                             ? 'active'
                             : '',
                           pItem.padding ? 'padding' : '',
+                          pItem.paraIndex == paraIndex &&
+                          pItem.sentIndex == sentIndex
+                            ? 'overActive'
+                            : '',
+                          curTime >=
+                            item.timeList[pItem.sentIndex].wordsResultList[
+                              pItem.wordIndex
+                            ].wordBg &&
+                          curTime <= item.timeList[pItem.sentIndex].ed
+                            ? 'wordActive'
+                            : '',
                         ]"
                         >{{ pItem.chs }}</span
                       >
@@ -127,6 +164,8 @@ export default {
       top: 0,
       left: 0,
       articleImg: {}, // 文章图片
+      paraIndex: -1, //段落索引
+      sentIndex: -1, // 句子索引
     };
   },
   computed: {},
@@ -240,6 +279,15 @@ export default {
       this.curTime = time;
       this.$refs.audioLine.onTimeupdateTime(time / 1000);
     },
+    //经过每个词,高亮句子
+    handleMouseover(pItem) {
+      this.paraIndex = pItem.paraIndex;
+      this.sentIndex = pItem.sentIndex;
+    },
+    handleMouseleave() {
+      this.paraIndex = -1;
+      this.sentIndex = -1;
+    },
   },
   //生命周期 - 创建完成(可以访问当前this实例)
   created() {},
@@ -265,6 +313,7 @@ export default {
   width: 100%;
   .NPC-sentences-list {
     padding: 24px 0;
+    color: rgba(0, 0, 0, 0.85);
   }
   .NNPE-detail {
     clear: both;
@@ -273,6 +322,7 @@ export default {
     .NNPE-words {
       float: left;
       padding: 0 0px 8px 0px;
+
       &-box {
         float: left;
         > span {
@@ -281,7 +331,7 @@ export default {
             font-family: "GB-PINYINOK-B";
             font-weight: normal;
             font-size: 14px;
-            line-height: 150%;
+            line-height: 22px;
             color: #000000;
             height: 21px;
             &.textLeft {
@@ -290,11 +340,17 @@ export default {
           }
           &.NNPE-chs {
             font-family: "FZJCGFKTK";
-            font-size: 24px;
-            line-height: 150%;
+            font-size: 20px;
+            line-height: 50px;
             color: #000000;
             &.active {
-              background: rgba(60, 200, 99, 0.2);
+              background: rgba(222, 68, 68, 0.15);
+            }
+            &.overActive {
+              background: rgba(0, 0, 0, 0.06);
+            }
+            &.wordActive {
+              color: rgba(222, 68, 68, 1);
             }
           }
           &.padding {
@@ -314,7 +370,7 @@ export default {
           font-family: "GB-PINYINOK-B";
           font-weight: normal;
           font-size: 14px;
-          line-height: 150%;
+          line-height: 22px;
           color: #000000;
           height: 21px;
           &.textLeft {
@@ -323,11 +379,17 @@ export default {
         }
         &.NNPE-chs {
           font-family: "FZJCGFKTK";
-          font-size: 24px;
-          line-height: 150%;
+          font-size: 20px;
+          line-height: 50px;
           color: #000000;
           &.active {
-            background: rgba(60, 200, 99, 0.2);
+            background: rgba(222, 68, 68, 0.15);
+          }
+          &.overActive {
+            background: rgba(0, 0, 0, 0.06);
+          }
+          &.wordActive {
+            color: rgba(222, 68, 68, 1);
           }
         }
         &.padding {

+ 7 - 6
src/components/Adult/preview/ArticleViewChs/PhraseModelChs.vue

@@ -343,6 +343,7 @@ export default {
   .NNPE-detail {
     clear: both;
     overflow: hidden;
+    color: rgba(0, 0, 0, 0.65);
     .NNPE-words {
       float: left;
       padding: 0 0px 8px 0px;
@@ -355,7 +356,7 @@ export default {
             font-weight: normal;
             font-size: 14px;
             line-height: 150%;
-            color: #000000;
+
             height: 21px;
             &.textLeft {
               text-align: left;
@@ -365,9 +366,9 @@ export default {
             font-family: "FZJCGFKTK";
             font-size: 24px;
             line-height: 150%;
-            color: #000000;
+
             &.active {
-              color: #e35454;
+              color: #de4444;
             }
           }
           &.padding {
@@ -388,7 +389,7 @@ export default {
           font-weight: normal;
           font-size: 14px;
           line-height: 150%;
-          color: #000000;
+
           height: 21px;
           &.textLeft {
             text-align: left;
@@ -398,9 +399,9 @@ export default {
           font-family: "FZJCGFKTK";
           font-size: 24px;
           line-height: 150%;
-          color: #000000;
+
           &.active {
-            color: #e35454;
+            color: #de4444;
           }
         }
         &.padding {

+ 22 - 8
src/components/Adult/preview/ArticleViewChs/WordModelChs.vue

@@ -21,7 +21,7 @@
                 v-for="(pItem, pIndex) in item.wordsList"
                 :key="'wordsList' + pIndex"
                 :class="[pItem.wordIndex == 0 ? 'textLeft' : 'textCenter']"
-                @click="showWordDetail($event, pItem.chs, pItem.pinyin)"
+                @click="showWordDetail($event, pItem)"
               >
                 <template v-if="!pItem.width">
                   <template v-if="pItem.isShow">
@@ -44,6 +44,11 @@
                             curTime <= item.timeList[pItem.sentIndex].ed
                               ? 'active'
                               : '',
+                            paraIndex == pItem.paraIndex &&
+                            sentIndex == pItem.sentIndex &&
+                            wordIndex == pItem.wordIndex
+                              ? 'wordActive'
+                              : '',
                           ]"
                           >{{ pItem.chs }}</span
                         >
@@ -141,6 +146,9 @@ export default {
       left: 0,
       contentWidth: 732,
       articleImg: {}, // 文章图片
+      paraIndex: -1,
+      sentIndex: -1,
+      wordIndex: -1,
     };
   },
   computed: {},
@@ -265,13 +273,16 @@ export default {
       this.curTime = time;
       this.$refs.audioLine.onTimeupdateTime(time / 1000);
     },
-    showWordDetail(e, word, pinyin) {
+    showWordDetail(e, item) {
       let _this = this;
       if (_this.oldHz != word) {
         this.isShow = false;
         setTimeout(() => {
-          _this.hz = word;
-          _this.pinyin = pinyin;
+          _this.hz = item.chs;
+          _this.pinyin = item.pinyin;
+          _this.paraIndex = item.paraIndex;
+          _this.sentIndex = item.sentIndex;
+          _this.wordIndex = item.wordIndex;
         }, 50);
       }
       _this.top = e.clientY + 20;
@@ -350,6 +361,7 @@ export default {
   .NNPE-detail {
     clear: both;
     overflow: hidden;
+    color: rgba(0, 0, 0, 0.85);
     .NNPE-words {
       float: left;
       padding: 0 0px 8px 0px;
@@ -362,7 +374,6 @@ export default {
             font-weight: normal;
             font-size: 14px;
             line-height: 150%;
-            color: #000000;
             height: 21px;
             &.textLeft {
               text-align: left;
@@ -372,10 +383,12 @@ export default {
             font-family: "FZJCGFKTK";
             font-size: 24px;
             line-height: 150%;
-            color: #000000;
             &.active {
               background: rgba(60, 200, 99, 0.2);
             }
+            &.wordActive {
+              color: #de4444;
+            }
           }
           &.padding {
             padding: 0 3px;
@@ -395,7 +408,6 @@ export default {
           font-weight: normal;
           font-size: 14px;
           line-height: 150%;
-          color: #000000;
           height: 21px;
           &.textLeft {
             text-align: left;
@@ -405,10 +417,12 @@ export default {
           font-family: "FZJCGFKTK";
           font-size: 24px;
           line-height: 150%;
-          color: #000000;
           &.active {
             background: rgba(60, 200, 99, 0.2);
           }
+          &.wordActive {
+            color: #de4444;
+          }
         }
         &.padding {
           padding: 0 3px;

+ 7 - 1
src/components/Adult/preview/ArticleViewChs/index.vue

@@ -179,7 +179,7 @@ export default {
     box-sizing: border-box;
     border-radius: 8px;
     overflow: hidden;
-    background: #f0f5fa;
+    background: #fff;
     box-sizing: border-box;
     .aduioLine-box {
       border-bottom: 1px solid rgba(0, 0, 0, 0.1);
@@ -218,4 +218,10 @@ export default {
     }
   }
 }
+.ArticleView-body {
+  .aduioLine-box {
+    border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+    width: 100%;
+  }
+}
 </style>

+ 422 - 0
src/components/Adult/preview/DialogueArticleViewChs/NormalModelChs.vue

@@ -0,0 +1,422 @@
+<!--  -->
+<template>
+  <div class="NNPE-ArticleView" v-if="curQue">
+    <div v-if="curQue.mp3_list.length > 0 && curQue.mp3_list[0].url">
+      <AudioLine
+        :mp3="curQue.mp3_list[0].url"
+        :getCurTime="getCurTime"
+        ref="audioLine"
+      />
+    </div>
+    <template v-if="resArr.length > 0">
+      <div class="NPC-sentences-list">
+        <div
+          :class="['NNPE-detail', item.isTitle ? 'NNPE-detail-title' : '']"
+          v-for="(item, index) in resArr"
+          :key="'detail' + index"
+        >
+          <div
+            :class="[
+              'article-content',
+              index == 0 ? 'paraFirst' : '',
+              index == resArr.length - 1 ? 'paraLast' : '',
+            ]"
+          >
+            <RoleChs :curRole="item.roleDetail" />
+            <div class="wordsList-box">
+              <img
+                :src="articleImg[index]"
+                v-if="articleImg[0] && index == 0"
+              />
+              <div>
+                <div
+                  class="NNPE-words"
+                  v-for="(pItem, pIndex) in item.wordsList"
+                  :key="'wordsList' + pIndex"
+                  :class="[pItem.wordIndex == 0 ? 'textLeft' : 'textCenter']"
+                  @click="handleChangeTime(item.timeList[pItem.sentIndex].bg)"
+                >
+                  <template v-if="!pItem.width">
+                    <template v-if="pItem.isShow">
+                      <template
+                        v-if="
+                          item.wordsList[pIndex + 1].chs &&
+                          chsFhList.indexOf(item.wordsList[pIndex + 1].chs) > -1
+                        "
+                      >
+                        <span class="NNPE-words-box">
+                          <span
+                            class="NNPE-pinyin"
+                            :class="[pItem.className ? pItem.className : '']"
+                            >{{ pItem.pinyin }}</span
+                          >
+                          <span
+                            class="NNPE-chs"
+                            :class="[
+                              curTime >= item.timeList[pItem.sentIndex].bg &&
+                              curTime <= item.timeList[pItem.sentIndex].ed
+                                ? 'active'
+                                : '',
+                            ]"
+                            >{{ pItem.chs }}</span
+                          >
+                        </span>
+                        <span class="NNPE-words-box">
+                          <span class="NNPE-pinyin" style="text-align: left">{{
+                            item.wordsList[pIndex + 1].pinyin
+                          }}</span>
+                          <span
+                            class="NNPE-chs"
+                            style="text-align: left"
+                            :class="[
+                              curTime >= item.timeList[pItem.sentIndex].bg &&
+                              curTime <= item.timeList[pItem.sentIndex].ed
+                                ? 'active'
+                                : '',
+                            ]"
+                            >{{ item.wordsList[pIndex + 1].chs }}</span
+                          >
+                        </span>
+                      </template>
+                      <template v-else>
+                        <span
+                          class="NNPE-pinyin"
+                          :class="[
+                            pItem.padding ? 'padding' : '',
+                            pItem.className ? pItem.className : '',
+                          ]"
+                          >{{ pItem.pinyin }}</span
+                        >
+                        <span
+                          class="NNPE-chs"
+                          :class="[
+                            curTime >= item.timeList[pItem.sentIndex].bg &&
+                            curTime <= item.timeList[pItem.sentIndex].ed
+                              ? 'active'
+                              : '',
+                            pItem.padding ? 'padding' : '',
+                          ]"
+                          >{{ pItem.chs }}</span
+                        >
+                      </template>
+                    </template>
+                  </template>
+                  <template v-else>
+                    <span
+                      :style="{
+                        height: pItem.height + 'px',
+                        width: pItem.width + 'px',
+                      }"
+                    ></span>
+                  </template>
+                </div>
+              </div>
+              <img :src="articleImg[index + 1]" v-if="articleImg[index + 1]" />
+            </div>
+          </div>
+          <div class="remarkBox" :class="index == 0 ? 'remark72' : 'remark40'">
+            <RemarkChs :remarkDetail="item.remarkDetail" />
+          </div>
+        </div>
+      </div>
+    </template>
+  </div>
+</template>
+
+<script>
+import { timeStrToSen } from "@/utils/index";
+import AudioLine from "../AudioLine.vue";
+import RoleChs from "./RoleChs.vue";
+import RemarkChs from "./RemarkChs.vue";
+export default {
+  name: "DialogueNormalModelChs",
+  props: ["curQue"],
+  components: {
+    AudioLine,
+    RoleChs,
+    RemarkChs,
+  },
+  data() {
+    return {
+      resArr: [],
+      curTime: 0, //单位s
+      chsFhList: [",", "。", "“", ":", "》", "《", "?", "!", ";"],
+      enFhList: [",", ".", ";", "?", "!", ":", ">", "<"],
+      newWords: ["鱼", "辩礼义"],
+      oldHz: "",
+      hz: "",
+      top: 0,
+      left: 0,
+      articleImg: {}, // 文章图片
+    };
+  },
+  computed: {},
+  watch: {},
+  //方法集合
+  methods: {
+    getCurTime(curTime) {
+      this.curTime = curTime * 1000;
+    },
+    handleData() {
+      let resArr = [];
+
+      let leg = this.curQue.detail.length;
+      let curQue = JSON.parse(JSON.stringify(this.curQue));
+      curQue.detail.forEach((dItem, dIndex) => {
+        let roleDetail = this.getRole(dItem);
+        let remarkDetail = dItem.remark;
+        let paraArr = [];
+        dItem.wordsList.forEach((sItem, sIndex) => {
+          sItem.forEach((wItem, wIndex) => {
+            //this.judgePad(sItem, wItem, wIndex);
+            this.mergeWordSymbol(sItem, wItem, wIndex);
+            let obj = {
+              paraIndex: dIndex, //段落索引
+              sentIndex: sIndex, //在段落中句子索引
+              //articleSentIndex: asIndex, //在文章中句子索引
+              wordIndex: wIndex, //单词的索引
+              pinyin: wItem.pinyin,
+              chs: wItem.chs,
+              padding: true, //wItem.padding,
+              className: wItem.className,
+              isShow: wItem.isShow,
+              isNewWord: this.newWords.indexOf(wItem.chs) > -1 ? true : false,
+            };
+            paraArr.push(obj);
+          });
+        });
+        let curSentencesLeg = dItem.sentences.length;
+        let startLeg = dIndex == 0 ? 0 : curQue.detail[dIndex - 1].endLeg;
+        let endLeg = startLeg + curSentencesLeg;
+        dItem.endLeg = endLeg;
+        let timeList = curQue.wordTime.slice(startLeg, endLeg);
+        let paraObj = {
+          wordsList: paraArr,
+          timeList: timeList,
+          roleDetail: roleDetail,
+          remarkDetail: remarkDetail,
+        };
+        resArr.push(paraObj);
+      });
+      this.resArr = resArr;
+      console.log("Normal");
+      console.log(this.resArr);
+
+      // 循环文章图片
+      if (curQue.img_list) {
+        curQue.img_list.forEach((item) => {
+          this.articleImg[item.imgNumber] = item.url;
+        });
+      }
+    },
+    //词和标点合一起
+    mergeWordSymbol(sItem, wItem, curIndex) {
+      let leg = sItem.length;
+      if (curIndex < leg - 1) {
+        if (this.chsFhList.indexOf(wItem.chs) > -1) {
+          wItem.isShow = false;
+        } else {
+          wItem.isShow = true;
+        }
+      }
+    },
+    //获取角色
+    getRole(dItem) {
+      let roleIndex = dItem.roleIndex;
+      let resArr = this.curQue.roleList.filter((item) => item.id == roleIndex);
+      return resArr[0];
+    },
+    //判断是否有padding
+    judgePad(sItem, wItem, curIndex) {
+      let leg = sItem.length;
+      if (curIndex < leg - 1) {
+        let nextIndex = curIndex + 1;
+        let chs = sItem[nextIndex].chs;
+        if (
+          this.chsFhList.indexOf(chs) > -1 ||
+          this.chsFhList.indexOf(wItem.chs) > -1
+        ) {
+          wItem.padding = false;
+        } else {
+          wItem.padding = true;
+        }
+        if (this.enFhList.indexOf(wItem.pinyin) > -1) {
+          wItem.className = "textLeft";
+        }
+      }
+    },
+    //转化时间
+    handleTimeList(list) {
+      let listRes = [];
+      list.forEach((item) => {
+        let res = timeStrToSen(item);
+        listRes.push(res);
+      });
+      return listRes;
+    },
+    //点击播放某个句子
+    handleChangeTime(time) {
+      this.curTime = time;
+      this.$refs.audioLine.onTimeupdateTime(time / 1000);
+    },
+  },
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {
+    console.log(this.curQue);
+    if (this.curQue) {
+      this.handleData();
+    }
+  },
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+.NNPE-ArticleView {
+  width: 100%;
+  .NPC-sentences-list {
+  }
+  .NNPE-detail {
+    clear: both;
+    overflow: hidden;
+    display: flex;
+    justify-content: flex-start;
+    align-items: flex-start;
+    .article-content {
+      width: 553px;
+      box-sizing: border-box;
+      border-right: 1px rgba(0, 0, 0, 0.1) solid;
+      padding: 8px 23px;
+      &.paraFirst {
+        padding-top: 32px;
+      }
+      &.paraLast {
+        padding-bottom: 32px;
+      }
+    }
+    .NNPE-words {
+      float: left;
+      padding: 0 0px 8px 0px;
+      &-box {
+        float: left;
+        > span {
+          display: block;
+          &.NNPE-pinyin {
+            font-family: "GB-PINYINOK-B";
+            font-weight: normal;
+            font-size: 14px;
+            line-height: 22px;
+            color: #000000;
+            height: 21px;
+            &.textLeft {
+              text-align: left;
+            }
+          }
+          &.NNPE-chs {
+            font-family: "FZJCGFKTK";
+            font-size: 20px;
+            line-height: 28px;
+            color: #000000;
+            &.active {
+              background: rgba(60, 200, 99, 0.2);
+            }
+          }
+          &.padding {
+            padding: 0 3px;
+          }
+        }
+      }
+      &.textLeft {
+        text-align: left;
+      }
+      &.textCenter {
+        text-align: center;
+      }
+      > span {
+        display: block;
+        &.NNPE-pinyin {
+          font-family: "GB-PINYINOK-B";
+          font-weight: normal;
+          font-size: 14px;
+          line-height: 22px;
+          color: #000000;
+          height: 21px;
+          &.textLeft {
+            text-align: left;
+          }
+        }
+        &.NNPE-chs {
+          font-family: "FZJCGFKTK";
+          font-size: 20px;
+          line-height: 28px;
+          color: #000000;
+          &.active {
+            background: rgba(60, 200, 99, 0.2);
+          }
+        }
+        &.padding {
+          padding: 0 3px;
+        }
+      }
+    }
+    &.NNPE-detail-title {
+      .wordsList-box {
+        > div {
+          display: flex;
+          justify-content: center;
+        }
+      }
+    }
+    .index {
+      width: 48px;
+      box-sizing: border-box;
+      padding: 8px;
+      text-align: right;
+      border-right: 1px solid rgba(0, 0, 0, 0.1);
+      b {
+        font-weight: 400;
+        color: #000000;
+        line-height: 1.5;
+      }
+    }
+
+    .wordsList-box {
+      width: 100%;
+      padding: 0px 24px 0px 40px;
+      clear: both;
+      overflow: hidden;
+      > div {
+        float: left;
+        border: 1px solid rgba(0, 0, 0, 0.1);
+        box-sizing: border-box;
+        padding: 8px 12px 0px 12px;
+        border-radius: 8px;
+      }
+      > img {
+        width: 100%;
+        display: block;
+      }
+    }
+  }
+  .remarkBox {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    &.remark72 {
+      padding-top: 72px;
+    }
+    &.remark40 {
+      padding-top: 40px;
+    }
+  }
+}
+</style>

+ 451 - 0
src/components/Adult/preview/DialogueArticleViewChs/PhraseModelChs.vue

@@ -0,0 +1,451 @@
+<!--  -->
+<template>
+  <div class="NNPE-ArticleView" v-if="curQue">
+    <AudioLine
+      :mp3="curQue.mp3_list[0].url"
+      :getCurTime="getCurTime"
+      ref="audioLine"
+    />
+    <template v-if="resArr.length > 0">
+      <div class="NPC-sentences-list">
+        <div
+          :class="['NNPE-detail', item.isTitle ? 'NNPE-detail-title' : '']"
+          v-for="(item, index) in resArr"
+          :key="'detail' + index"
+        >
+          <div class="wordsList-box">
+            <img :src="articleImg[index]" v-if="articleImg[0] && index == 0" />
+            <div>
+              <div
+                class="NNPE-words"
+                v-for="(pItem, pIndex) in item.wordsList"
+                :key="'wordsList' + pIndex"
+                :class="[pItem.wordIndex == 0 ? 'textLeft' : 'textCenter']"
+                @click="showWordDetail($event, pItem.chs)"
+              >
+                <template v-if="!pItem.width">
+                  <template v-if="pItem.isShow">
+                    <template
+                      v-if="
+                        item.wordsList[pIndex + 1].chs &&
+                        chsFhList.indexOf(item.wordsList[pIndex + 1].chs) > -1
+                      "
+                    >
+                      <span class="NNPE-words-box">
+                        <span
+                          class="NNPE-pinyin"
+                          :class="[pItem.className ? pItem.className : '']"
+                          >{{ pItem.pinyin }}</span
+                        >
+                        <span
+                          :class="[
+                            'NNPE-chs',
+                            newWordList.indexOf(pItem.chs) > -1 ? 'active' : '',
+                          ]"
+                          >{{ pItem.chs }}</span
+                        >
+                      </span>
+                      <span class="NNPE-words-box">
+                        <span class="NNPE-pinyin" style="text-align: left">{{
+                          item.wordsList[pIndex + 1].pinyin
+                        }}</span>
+                        <span class="NNPE-chs" style="text-align: left">{{
+                          item.wordsList[pIndex + 1].chs
+                        }}</span>
+                      </span>
+                    </template>
+                    <template v-else>
+                      <span
+                        class="NNPE-pinyin"
+                        :class="[
+                          pItem.padding ? 'padding' : '',
+                          pItem.className ? pItem.className : '',
+                        ]"
+                        >{{ pItem.pinyin }}</span
+                      >
+                      <span
+                        class="NNPE-chs"
+                        :class="[
+                          pItem.padding ? 'padding' : '',
+                          newWordList.indexOf(pItem.chs) > -1 ? 'active' : '',
+                        ]"
+                        >{{ pItem.chs }}</span
+                      >
+                    </template>
+                  </template>
+                </template>
+                <template v-else>
+                  <span
+                    :style="{
+                      height: pItem.height + 'px',
+                      width: pItem.width + 'px',
+                    }"
+                  ></span>
+                </template>
+              </div>
+            </div>
+            <img :src="articleImg[index + 1]" v-if="articleImg[index + 1]" />
+          </div>
+        </div>
+      </div>
+    </template>
+    <template v-if="isShow">
+      <div
+        class="NNPE-wordDetail"
+        :style="{ top: top + 'px', left: left + 'px' }"
+      >
+        <Wordcard :word="word" :changeWordCard="changeWordCard" />
+      </div>
+    </template>
+  </div>
+</template>
+
+<script>
+import { timeStrToSen } from "@/utils/index";
+import AudioLine from "../AudioLine.vue";
+import Wordcard from "../components/Wordcard.vue"; // 卡片
+export default {
+  name: "PhraseModelChs",
+  props: ["curQue", "bodyLeft", "NNPENewWordList"],
+  components: {
+    AudioLine,
+    Wordcard,
+  },
+  data() {
+    return {
+      resArr: [],
+      curTime: 0, //单位s
+      chsFhList: [",", "。", "“", ":", "》", "《", "?", "!", ";"],
+      enFhList: [",", ".", ";", "?", "!", ":", ">", "<"],
+      newWords: ["鱼", "辩礼义"],
+      oldHz: "",
+      hz: "",
+      top: 0,
+      left: 0,
+      articleImg: {}, // 文章图片
+      newWordList: [],
+      word: null,
+      isShow: false,
+    };
+  },
+  computed: {},
+  watch: {
+    hz: {
+      handler: function (val, oldVal) {
+        let _this = this;
+        if (val) {
+          _this.handleNewWords(val, _this.top, _this.left);
+        }
+      },
+      // 深度观察监听
+      deep: true,
+    },
+  },
+  //方法集合
+  methods: {
+    getCurTime(curTime) {
+      this.curTime = curTime;
+    },
+    handleData() {
+      let resArr = [];
+      let leg = this.curQue.detail.length;
+      let curQue = JSON.parse(JSON.stringify(this.curQue));
+      curQue.detail.forEach((dItem, dIndex) => {
+        let paraArr = [
+          {
+            pinyin: "",
+            chs: "",
+            width: 20,
+            height: 20,
+          },
+          {
+            width: 20,
+            height: 20,
+            pinyin: "",
+            chs: "",
+          },
+        ];
+        dItem.wordsList.forEach((sItem, sIndex) => {
+          sItem.forEach((wItem, wIndex) => {
+            //this.judgePad(sItem, wItem, wIndex);
+            this.mergeWordSymbol(sItem, wItem, wIndex);
+            let obj = {
+              paraIndex: dIndex, //段落索引
+              sentIndex: sIndex, //在段落中句子索引
+              wordIndex: wIndex, //单词的索引
+              pinyin: wItem.pinyin,
+              chs: wItem.chs,
+              padding: true, //wItem.padding,
+              className: wItem.className,
+              isShow: wItem.isShow,
+              isNewWord: this.newWords.indexOf(wItem.chs) > -1 ? true : false,
+            };
+            paraArr.push(obj);
+          });
+        });
+
+        let paraObj = {
+          wordsList: paraArr,
+        };
+        resArr.push(paraObj);
+      });
+      this.resArr = resArr;
+      console.log(this.resArr);
+
+      // 循环文章图片
+      if (curQue.img_list) {
+        curQue.img_list.forEach((item) => {
+          this.articleImg[item.imgNumber] = item.url;
+        });
+      }
+    },
+    //词和标点合一起
+    mergeWordSymbol(sItem, wItem, curIndex) {
+      let leg = sItem.length;
+      if (curIndex < leg - 1) {
+        let nextIndex = curIndex + 1;
+        let chs = sItem[nextIndex].chs;
+        let pinyin = sItem[nextIndex].pinyin;
+        // if (this.chsFhList.indexOf(chs) > -1) {
+        //   wItem.chs = "<a>" + wItem.chs + "</a><a>" + chs + "</a>";
+        //   wItem.pinyin = "<a>" + wItem.pinyin + "</a><a>" + pinyin + "</a>";
+        // }
+        if (this.chsFhList.indexOf(wItem.chs) > -1) {
+          wItem.isShow = false;
+        } else {
+          wItem.isShow = true;
+        }
+      }
+
+      // if (this.enFhList.indexOf(wItem.pinyin) > -1) {
+      //   wItem.className = "textLeft";
+      // }
+    },
+    //判断是否有padding
+    judgePad(sItem, wItem, curIndex) {
+      let leg = sItem.length;
+      if (curIndex < leg - 1) {
+        let nextIndex = curIndex + 1;
+        let chs = sItem[nextIndex].chs;
+        if (
+          this.chsFhList.indexOf(chs) > -1 ||
+          this.chsFhList.indexOf(wItem.chs) > -1
+        ) {
+          wItem.padding = false;
+        } else {
+          wItem.padding = true;
+        }
+        if (this.enFhList.indexOf(wItem.pinyin) > -1) {
+          wItem.className = "textLeft";
+        }
+      }
+    },
+    //转化时间
+    handleTimeList(list) {
+      let listRes = [];
+      list.forEach((item) => {
+        let res = timeStrToSen(item);
+        listRes.push(res);
+      });
+      return listRes;
+    },
+    //点击播放某个句子
+    handleChangeTime(time) {
+      this.curTime = time;
+      this.$refs.audioLine.onTimeupdateTime(time);
+    },
+    handleNewword() {
+      let NewWordList = [];
+      this.NNPENewWordList.forEach((item) => {
+        NewWordList.push(item.new_word);
+      });
+      this.newWordList = JSON.parse(JSON.stringify(NewWordList));
+    },
+
+    showWordDetail(e, word) {
+      let _this = this;
+      if (_this.oldHz != word) {
+        this.isShow = false;
+        setTimeout(() => {
+          _this.hz = word;
+        }, 50);
+      }
+      _this.top = e.clientY + 20;
+      let left = e.clientX;
+      let width = 0;
+      if (word.length == 1 || word.length == 2) {
+        width = 304;
+      } else if (word.length == 3 || word.length == 4) {
+        width = 432;
+      } else if (word.length > 3) {
+        width = 560;
+      }
+      if (left - this.bodyLeft > this.contentWidth / 2) {
+        _this.left = left - width;
+      } else {
+        _this.left = left;
+      }
+    },
+    hideWordDetail() {
+      this.isShow = false;
+    },
+    changeWordCard(isShow) {
+      this.isShow = isShow;
+      this.oldHz = "";
+      this.hz = "";
+    },
+    // 处理分词数据
+    handleNewWords(val, top, left) {
+      debugger;
+      this.isShow = true;
+      this.word = null;
+      for (let i = 0; i < this.NNPENewWordList.length; i++) {
+        let item = this.NNPENewWordList[i];
+        if (item.new_word.trim() == val.trim()) {
+          let wordlist = val.split("");
+          this.word = { list: wordlist, detail: item, top: top, left: left };
+          break;
+        }
+      }
+      this.oldHz = val;
+    },
+  },
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {
+    console.log(this.curQue);
+    if (this.curQue) {
+      this.handleData();
+    }
+    console.log("生词");
+    console.log(this.NNPENewWordList);
+    if (this.NNPENewWordList && this.NNPENewWordList.length > 0) {
+      this.handleNewword();
+    }
+  },
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+.NNPE-ArticleView {
+  width: 100%;
+  .NPC-sentences-list {
+    padding: 24px 0;
+  }
+  .NNPE-detail {
+    clear: both;
+    overflow: hidden;
+    .NNPE-words {
+      float: left;
+      padding: 0 0px 8px 0px;
+      &-box {
+        float: left;
+        > span {
+          display: block;
+          &.NNPE-pinyin {
+            font-family: "GB-PINYINOK-B";
+            font-weight: normal;
+            font-size: 14px;
+            line-height: 150%;
+            color: #000000;
+            height: 21px;
+            &.textLeft {
+              text-align: left;
+            }
+          }
+          &.NNPE-chs {
+            font-family: "FZJCGFKTK";
+            font-size: 24px;
+            line-height: 150%;
+            color: #000000;
+            &.active {
+              color: #e35454;
+            }
+          }
+          &.padding {
+            padding: 0 3px;
+          }
+        }
+      }
+      &.textLeft {
+        text-align: left;
+      }
+      &.textCenter {
+        text-align: center;
+      }
+      > span {
+        display: block;
+        &.NNPE-pinyin {
+          font-family: "GB-PINYINOK-B";
+          font-weight: normal;
+          font-size: 14px;
+          line-height: 150%;
+          color: #000000;
+          height: 21px;
+          &.textLeft {
+            text-align: left;
+          }
+        }
+        &.NNPE-chs {
+          font-family: "FZJCGFKTK";
+          font-size: 24px;
+          line-height: 150%;
+          color: #000000;
+          &.active {
+            color: #e35454;
+          }
+        }
+        &.padding {
+          padding: 0 3px;
+        }
+      }
+    }
+    &.NNPE-detail-title {
+      .wordsList-box {
+        > div {
+          display: flex;
+          justify-content: center;
+        }
+      }
+    }
+    .index {
+      width: 48px;
+      box-sizing: border-box;
+      padding: 8px;
+      text-align: right;
+      border-right: 1px solid rgba(0, 0, 0, 0.1);
+      b {
+        font-weight: 400;
+        color: #000000;
+        line-height: 1.5;
+      }
+    }
+    .wordsList-box {
+      width: 100%;
+      padding: 6px 24px 12px 24px;
+      > div {
+        overflow: hidden;
+        clear: both;
+      }
+      > img {
+        width: 100%;
+        display: block;
+      }
+    }
+  }
+  .NNPE-wordDetail {
+    position: fixed;
+    //   width: 260px;
+    //   height: 200px;
+    //   background: #cc0;
+  }
+}
+</style>

+ 475 - 0
src/components/Adult/preview/DialogueArticleViewChs/Practicechs.vue

@@ -0,0 +1,475 @@
+<!--  -->
+<template>
+  <div class="NNPE-ArticleView" v-if="curQue">
+    <AudioLine
+      :mp3="curQue.mp3_list[0].url"
+      v-if="curQue.mp3_list[0].url"
+      class="aduioLine-box"
+      :getCurTime="getCurTime"
+      ref="audioLine"
+      :stopAudio="stopAudio"
+      @handleChangeStopAudio="handleChangeStopAudio"
+    />
+    <template v-if="resObj">
+      <!--  -->
+      <div class="NPC-sentences-list">
+        <div v-for="(item, index) in resObj.sentList" :key="'detail' + index">
+          <div
+            class="NNPE-detail"
+            @click="handleChangeTime(curQue.wordTime[index].bg)"
+          >
+            <div
+              class="NNPE-words"
+              v-for="(pItem, pIndex) in item"
+              :key="'wordsList' + pIndex"
+              :class="[pItem.wordIndex == 0 ? 'textLeft' : 'textCenter']"
+            >
+              <template v-if="!pItem.width">
+                <template v-if="pItem.isShow">
+                  <template
+                    v-if="
+                      item[pIndex + 1].chs &&
+                      chsFhList.indexOf(item[pIndex + 1].chs) > -1
+                    "
+                  >
+                    <span class="NNPE-words-box">
+                      <span
+                        class="NNPE-pinyin"
+                        :class="[pItem.className ? pItem.className : '']"
+                        >{{ pItem.pinyin }}</span
+                      >
+                      <span
+                        class="NNPE-chs"
+                        :class="[pItem.padding ? 'padding' : '']"
+                      >
+                        <template
+                          v-if="pItem.timeList && pItem.timeList.length > 0"
+                        >
+                          <span
+                            v-for="(wItem, wIndex) in pItem.leg"
+                            :key="'ci' + wIndex + pIndex + index"
+                            :class="[
+                              pItem.timeList[wIndex] &&
+                              curTime >= pItem.timeList[wIndex].wordBg &&
+                              curTime <= curQue.wordTime[index].ed
+                                ? 'active'
+                                : '',
+                            ]"
+                            >{{ pItem.chs[wIndex] }}</span
+                          >
+                        </template>
+                      </span>
+                    </span>
+                    <span class="NNPE-words-box">
+                      <span class="NNPE-pinyin" style="text-align: left">{{
+                        item[pIndex + 1].pinyin
+                      }}</span>
+                      <span class="NNPE-chs" style="text-align: left">
+                        <span
+                          :class="[
+                            pItem.timeList[pItem.leg - 1] &&
+                            curTime >= pItem.timeList[pItem.leg - 1].wordBg &&
+                            curTime <= curQue.wordTime[index].ed
+                              ? 'active'
+                              : '',
+                          ]"
+                        >
+                          {{ item[pIndex + 1].chs }}</span
+                        >
+                      </span>
+                    </span>
+                  </template>
+                  <template v-else>
+                    <span
+                      class="NNPE-pinyin"
+                      :class="[
+                        pItem.padding ? 'padding' : '',
+                        pItem.className ? pItem.className : '',
+                      ]"
+                      >{{ pItem.pinyin }}</span
+                    >
+                    <span
+                      class="NNPE-chs"
+                      :class="[pItem.padding ? 'padding' : '']"
+                    >
+                      <template
+                        v-if="pItem.timeList && pItem.timeList.length > 0"
+                      >
+                        <span
+                          v-for="(wItem, wIndex) in pItem.leg"
+                          :key="'ci' + wIndex + pIndex + index"
+                          :class="[
+                            pItem.timeList[wIndex] &&
+                            curTime >= pItem.timeList[wIndex].wordBg &&
+                            curTime <= curQue.wordTime[index].ed
+                              ? 'active'
+                              : '',
+                          ]"
+                          >{{ pItem.chs[wIndex] }}</span
+                        >
+                      </template>
+                    </span>
+                  </template>
+                </template>
+              </template>
+              <template v-else>
+                <span
+                  :style="{
+                    height: pItem.height + 'px',
+                    width: pItem.width + 'px',
+                  }"
+                ></span>
+              </template>
+            </div>
+          </div>
+          <div
+            v-show="
+              curTime >= curQue.wordTime[index].bg &&
+              curTime <= curQue.wordTime[index].ed
+            "
+            class="Soundrecord-content"
+          >
+            <Soundrecord
+              @handleWav="handleWav"
+              type="pro"
+              class="luyin-box"
+              @handleParentPlay="handleParentPlay"
+            />
+          </div>
+        </div>
+      </div>
+    </template>
+  </div>
+</template>
+
+<script>
+import { timeStrToSen } from "@/utils/index";
+import AudioLine from "../AudioLine.vue";
+import Soundrecord from "../../preview/Soundrecord.vue"; // 录音模板
+export default {
+  name: "ArticleView",
+  props: ["curQue"],
+  components: {
+    AudioLine,
+    Soundrecord,
+  },
+  data() {
+    return {
+      resObj: null,
+      curTime: 0, //单位s
+      chsFhList: [",", "。", "“", ":", "》", "《", "?", "!", ";"],
+      enFhList: [",", ".", ";", "?", "!", ":", ">", "<"],
+      stopAudio: false,
+    };
+  },
+  computed: {},
+  watch: {},
+  //方法集合
+  methods: {
+    getCurTime(curTime) {
+      this.curTime = curTime * 1000;
+    },
+    handleData() {
+      let resArr = [],
+        timeArr = [];
+      let curQue = JSON.parse(JSON.stringify(this.curQue));
+      let wordTimeList = curQue.wordTime;
+      curQue.detail.forEach((dItem, dIndex) => {
+        dItem.wordsList.forEach((sItem, sIndex) => {
+          let sentArr = [];
+
+          sItem.forEach((wItem, wIndex) => {
+            let startIndex =
+              wIndex == 0
+                ? 0
+                : sentArr[wIndex - 1].startIndex +
+                  sentArr[wIndex - 1].chs.length;
+            let endIndex =
+              wIndex == 0
+                ? wItem.chs.length
+                : sentArr[wIndex - 1].endIndex + wItem.chs.length;
+            // this.judgePad(sItem, wItem, wIndex);
+            this.mergeWordSymbol(sItem, wItem, wIndex);
+            let obj = {
+              paraIndex: dIndex, //段落索引
+              sentIndex: sIndex, //在段落中句子索引
+              wordIndex: wIndex, //单词的索引
+              pinyin: wItem.pinyin,
+              chs: wItem.chs,
+              padding: true,
+              className: wItem.className,
+              isShow: wItem.isShow,
+              startIndex: startIndex,
+              endIndex: endIndex,
+              leg: wItem.chs.length,
+              timeList: [],
+            };
+            sentArr.push(obj);
+          });
+          resArr.push(sentArr);
+        });
+
+        timeArr.push(dItem.timeList);
+      });
+      this.mergeWordTime(resArr, wordTimeList);
+      let timeList = [];
+      timeArr.forEach((item) => {
+        item.forEach((aItem) => {
+          if (timeList.indexOf(aItem) < 0) {
+            timeList.push(aItem);
+          }
+        });
+      });
+      this.resObj = { sentList: resArr, timeList: timeList };
+      console.log(this.resObj);
+    },
+    mergeWordTime(resArr, wordTimeList) {
+      resArr.forEach((item, index) => {
+        let wordsResultList = wordTimeList[index].wordsResultList;
+        item.forEach((wItem) => {
+          let startIndex = wItem.startIndex;
+          let endIndex = wItem.endIndex;
+          wItem.timeList = wordsResultList.slice(startIndex, endIndex);
+        });
+      });
+    },
+    //词和标点合一起
+    mergeWordSymbol(sItem, wItem, curIndex) {
+      let leg = sItem.length;
+      if (curIndex < leg - 1) {
+        let nextIndex = curIndex + 1;
+
+        if (this.chsFhList.indexOf(wItem.chs) > -1) {
+          wItem.isShow = false;
+        } else {
+          wItem.isShow = true;
+        }
+      }
+    },
+    handleData2() {
+      let resArr = [],
+        timeArr = [];
+      let leg = this.curQue.detail.length;
+      let curQue = JSON.parse(JSON.stringify(this.curQue));
+      curQue.detail.forEach((dItem, dIndex) => {
+        let endTime = 0;
+        if (dIndex < leg - 1) {
+          endTime = curQue.detail[dIndex + 1].timeList[0];
+          dItem.timeList.push(endTime);
+          dItem.timeList = this.handleTimeList(dItem.timeList);
+        } else {
+          dItem.timeList = this.handleTimeList(dItem.timeList);
+          endTime = curQue.mp3_list[0].duration;
+          dItem.timeList.push(endTime);
+        }
+
+        dItem.wordsList.forEach((sItem, sIndex) => {
+          let time_diff = dItem.timeList[sIndex + 1] - dItem.timeList[sIndex];
+          let wordsLeg = dItem.sentences[sIndex].length;
+          let wordTime = time_diff / wordsLeg;
+          // console.log(time_diff, wordsLeg, wordTime);
+          let sentArr = [];
+          sItem.forEach((wItem, wIndex) => {
+            let preTotal = wIndex > 0 ? sentArr[wIndex - 1].endTime : 0;
+            let endTime =
+              wIndex > 0
+                ? wordTime * wItem.chs.length + preTotal
+                : dItem.timeList[sIndex] + wordTime * wItem.chs.length;
+            //console.log("endTime" + endTime);
+            let startTime =
+              wIndex > 0 ? sentArr[wIndex - 1].endTime : dItem.timeList[sIndex];
+            this.judgePad(sItem, wItem, wIndex);
+            let obj = {
+              paraIndex: dIndex, //段落索引
+              sentIndex: sIndex, //在段落中句子索引
+              wordIndex: wIndex, //单词的索引
+              pinyin: wItem.pinyin,
+              chs: wItem.chs,
+              padding: wItem.padding,
+              className: wItem.className,
+              startTime: startTime,
+              endTime: endTime,
+            };
+            sentArr.push(obj);
+          });
+          resArr.push(sentArr);
+        });
+
+        timeArr.push(dItem.timeList);
+      });
+      let timeList = [];
+      timeArr.forEach((item) => {
+        item.forEach((aItem) => {
+          if (timeList.indexOf(aItem) < 0) {
+            timeList.push(aItem);
+          }
+        });
+      });
+      this.resObj = { sentList: resArr, timeList: timeList };
+      console.log(this.resObj);
+    },
+    //判断是否有padding
+    judgePad(sItem, wItem, curIndex) {
+      let leg = sItem.length;
+      if (curIndex < leg - 1) {
+        let nextIndex = curIndex + 1;
+        let chs = sItem[nextIndex].chs;
+        if (
+          this.chsFhList.indexOf(chs) > -1 ||
+          this.chsFhList.indexOf(wItem.chs) > -1
+        ) {
+          wItem.padding = false;
+        } else {
+          wItem.padding = true;
+        }
+        if (this.enFhList.indexOf(wItem.pinyin) > -1) {
+          wItem.className = "textLeft";
+        }
+      }
+    },
+    //转化时间
+    handleTimeList(list) {
+      let listRes = [];
+      list.forEach((item) => {
+        let res = timeStrToSen(item);
+        listRes.push(res);
+      });
+      return listRes;
+    },
+    //计算总时间
+    countWordTime(sentArr) {
+      let total = 0;
+      sentArr.forEach((item) => {
+        total += item.endTime;
+      });
+      return total;
+    },
+    //点击播放某个句子
+    handleChangeTime(time) {
+      this.curTime = time;
+      this.$refs.audioLine.onTimeupdateTime(time / 1000);
+    },
+    handleWav(data) {},
+    // 录音时暂停音频播放
+    handleParentPlay() {
+      this.stopAudio = true;
+    },
+    // 音频播放时改变布尔值
+    handleChangeStopAudio() {
+      this.stopAudio = false;
+    },
+  },
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {
+    console.log(this.curQue);
+    if (this.curQue) {
+      this.handleData();
+    }
+  },
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+.NNPE-ArticleView {
+  width: 100%;
+  .NPC-sentences-list {
+    padding: 24px;
+  }
+  .Soundrecord-content {
+  }
+  .NNPE-detail {
+    clear: both;
+    overflow: hidden;
+    width: 100%;
+    background: #ffffff;
+    border: 1px solid rgba(0, 0, 0, 0.1);
+    box-sizing: border-box;
+    border-radius: 8px;
+    margin-bottom: 8px;
+    box-sizing: border-box;
+    padding: 8px 16px 0px;
+    .NNPE-words {
+      float: left;
+      padding: 0 0px 8px 0px;
+      &-box {
+        float: left;
+        > span {
+          display: block;
+          &.NNPE-pinyin {
+            font-family: "GB-PINYINOK-B";
+            font-weight: normal;
+            font-size: 14px;
+            line-height: 20px;
+            color: #000000;
+            height: 20px;
+            &.textLeft {
+              text-align: left;
+            }
+          }
+          &.NNPE-chs {
+            font-family: "FZJCGFKTK";
+            font-size: 20px;
+            line-height: 150%;
+            color: #000000;
+            .active {
+              color: #32a5d8;
+            }
+          }
+          // &.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: 14px;
+          line-height: 20px;
+          color: #000000;
+          height: 20px;
+          &.textLeft {
+            text-align: left;
+          }
+        }
+        &.NNPE-chs {
+          font-family: "FZJCGFKTK";
+          font-size: 20px;
+          line-height: 150%;
+          color: #000000;
+          .active {
+            color: #32a5d8;
+          }
+        }
+        &.padding {
+          padding: 0 3px;
+        }
+      }
+    }
+  }
+  .luyin-box {
+    width: 178px;
+    margin: 8px 0 8px 0px;
+    padding: 0 8px;
+    border: 1px solid rgba(0, 0, 0, 0.1);
+    border-radius: 8px;
+    background: #ffffff;
+  }
+}
+</style>

+ 74 - 0
src/components/Adult/preview/DialogueArticleViewChs/RemarkChs.vue

@@ -0,0 +1,74 @@
+<!--  -->
+<template>
+  <div class="remarkChs" v-if="remarkDetail">
+    <div class="remark-chs">{{ remarkDetail.chs }}</div>
+    <div class="remark-en">{{ remarkDetail.en }}</div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "RemarkChs",
+  components: {},
+  props: ["remarkDetail"],
+  data() {
+    return {};
+  },
+  computed: {},
+  watch: {},
+  //方法集合
+  methods: {},
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {},
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+.remarkChs {
+  width: 178px;
+  box-sizing: border-box;
+  box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
+  border-radius: 8px;
+  > .remark-chs {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    width: 100%;
+    background: #988ed6;
+    border: 1px solid rgba(0, 0, 0, 0.1);
+    box-sizing: border-box;
+    border-radius: 8px 8px 0px 0px;
+    font-size: 14px;
+    line-height: 22px;
+    color: #ffffff;
+    font-weight: normal;
+
+    box-sizing: border-box;
+    min-height: 34px;
+    text-align: center;
+  }
+  > .remark-en {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    border: 1px solid rgba(0, 0, 0, 0.1);
+    border-top: 0;
+    box-sizing: border-box;
+    min-height: 34px;
+    text-align: center;
+    font-size: 14px;
+    line-height: 22px;
+    color: #000000;
+    border-radius: 0px 0px 8px 8px;
+  }
+}
+</style>

+ 103 - 0
src/components/Adult/preview/DialogueArticleViewChs/RoleChs.vue

@@ -0,0 +1,103 @@
+<!--  -->
+<template>
+  <div class="role-rItem" v-if="curRole">
+    <span v-if="curRole.role" class="adult-book-input-roleText">{{
+      curRole.role
+    }}</span>
+    <img
+      v-else
+      :src="curRole.img_list[0] && curRole.img_list[0].url"
+      class="adult-book-input-roleImg"
+    />
+    <template v-if="curRole.detail.wordsList.length > 0">
+      <span class="pinyin">{{ curRole.detail.wordsList | handlePinyin }}</span>
+      <span class="chs">{{ curRole.detail.wordsList | handleChs }}</span>
+    </template>
+  </div>
+</template>
+
+<script>
+export default {
+  components: {},
+  props: ["curRole"],
+  filters: {
+    handlePinyin(wordsList) {
+      let str = "";
+      wordsList.forEach((item, index) => {
+        if (index < wordsList.length - 1) {
+          str += item.pinyin + " ";
+        } else {
+          str += item.pinyin;
+        }
+      });
+      return str;
+    },
+    handleChs(wordsList) {
+      let str = "";
+      wordsList.forEach((item, index) => {
+        if (index < wordsList.length - 1) {
+          str += item.chs + " ";
+        } else {
+          str += item.chs;
+        }
+      });
+      return str;
+    },
+  },
+  data() {
+    return {};
+  },
+  computed: {},
+  watch: {},
+  //方法集合
+  methods: {},
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {},
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+.role-rItem {
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+  .adult-book-input {
+    &-roleText {
+      width: 40px;
+      height: 40px;
+      background: #a7a7a7;
+      border-radius: 100%;
+      text-align: center;
+      line-height: 40px;
+    }
+    &-roleImg {
+      width: 40px;
+      height: 40px;
+    }
+  }
+  .pinyin {
+    font-family: "GB-PINYINOK-B";
+    font-size: 14px;
+    line-height: 22px;
+    color: rgba(0, 0, 0, 0.85);
+    margin-right: 8px;
+    margin-left: 8px;
+  }
+  .chs {
+    font-family: "FZJCGFKTK";
+    font-size: 16px;
+    line-height: 24px;
+    color: #000000;
+    margin-right: 16px;
+  }
+}
+</style>

+ 458 - 0
src/components/Adult/preview/DialogueArticleViewChs/WordModelChs.vue

@@ -0,0 +1,458 @@
+<!--  -->
+<template>
+  <div class="NNPE-ArticleView" v-if="curQue">
+    <AudioLine
+      :mp3="curQue.mp3_list[0].url"
+      :getCurTime="getCurTime"
+      ref="audioLine"
+    />
+    <template v-if="resArr.length > 0">
+      <div class="NPC-sentences-list">
+        <div
+          :class="['NNPE-detail', item.isTitle ? 'NNPE-detail-title' : '']"
+          v-for="(item, index) in resArr"
+          :key="'detail' + index"
+        >
+          <div class="wordsList-box">
+            <img :src="articleImg[index]" v-if="articleImg[0] && index == 0" />
+            <div>
+              <div
+                class="NNPE-words"
+                v-for="(pItem, pIndex) in item.wordsList"
+                :key="'wordsList' + pIndex"
+                :class="[pItem.wordIndex == 0 ? 'textLeft' : 'textCenter']"
+                @click="showWordDetail($event, pItem.chs, pItem.pinyin)"
+              >
+                <template v-if="!pItem.width">
+                  <template v-if="pItem.isShow">
+                    <template
+                      v-if="
+                        item.wordsList[pIndex + 1].chs &&
+                        chsFhList.indexOf(item.wordsList[pIndex + 1].chs) > -1
+                      "
+                    >
+                      <span class="NNPE-words-box">
+                        <span
+                          class="NNPE-pinyin"
+                          :class="[pItem.className ? pItem.className : '']"
+                          >{{ pItem.pinyin }}</span
+                        >
+                        <span
+                          class="NNPE-chs"
+                          :class="[
+                            curTime >= item.timeList[pItem.sentIndex].bg &&
+                            curTime <= item.timeList[pItem.sentIndex].ed
+                              ? 'active'
+                              : '',
+                          ]"
+                          >{{ pItem.chs }}</span
+                        >
+                      </span>
+                      <span class="NNPE-words-box">
+                        <span class="NNPE-pinyin" style="text-align: left">{{
+                          item.wordsList[pIndex + 1].pinyin
+                        }}</span>
+                        <span
+                          class="NNPE-chs"
+                          style="text-align: left"
+                          :class="[
+                            curTime >= item.timeList[pItem.sentIndex].bg &&
+                            curTime <= item.timeList[pItem.sentIndex].ed
+                              ? 'active'
+                              : '',
+                          ]"
+                          >{{ item.wordsList[pIndex + 1].chs }}</span
+                        >
+                      </span>
+                    </template>
+                    <template v-else>
+                      <span
+                        class="NNPE-pinyin"
+                        :class="[
+                          pItem.padding ? 'padding' : '',
+                          pItem.className ? pItem.className : '',
+                        ]"
+                        >{{ pItem.pinyin }}</span
+                      >
+                      <span
+                        class="NNPE-chs"
+                        :class="[
+                          curTime >= item.timeList[pItem.sentIndex].bg &&
+                          curTime <= item.timeList[pItem.sentIndex].ed
+                            ? 'active'
+                            : '',
+                          pItem.padding ? 'padding' : '',
+                        ]"
+                        >{{ pItem.chs }}</span
+                      >
+                    </template>
+                  </template>
+                </template>
+                <template v-else>
+                  <span
+                    :style="{
+                      height: pItem.height + 'px',
+                      width: pItem.width + 'px',
+                    }"
+                  ></span>
+                </template>
+              </div>
+            </div>
+            <img :src="articleImg[index + 1]" v-if="articleImg[index + 1]" />
+          </div>
+        </div>
+      </div>
+    </template>
+    <template v-if="isShow">
+      <div
+        class="NNPE-wordDetail"
+        :style="{ top: top + 'px', left: left + 'px' }"
+      >
+        <Wordcard :word="word" :changeWordCard="changeWordCard" />
+      </div>
+    </template>
+  </div>
+</template>
+
+<script>
+import { timeStrToSen } from "@/utils/index";
+import AudioLine from "../AudioLine.vue";
+import Wordcard from "../components/Wordcard.vue"; // 卡片
+export default {
+  name: "WordModelChs",
+  props: ["curQue", "bodyLeft", "NNPENewWordList"],
+  components: {
+    AudioLine,
+    Wordcard,
+  },
+  data() {
+    return {
+      resArr: [],
+      curTime: 0, //单位s
+      chsFhList: [",", "。", "“", ":", "》", "《", "?", "!", ";"],
+      enFhList: [",", ".", ";", "?", "!", ":", ">", "<"],
+      newWords: ["鱼", "辩礼义"],
+      isShow: false,
+      hz: "",
+      oldHz: "",
+      pinyin: "",
+      word: null,
+      top: 0,
+      left: 0,
+      contentWidth: 732,
+      articleImg: {}, // 文章图片
+    };
+  },
+  computed: {},
+  watch: {
+    hz: {
+      handler: function (val, oldVal) {
+        let _this = this;
+        if (val) {
+          _this.handleNewWords(val, _this.top, _this.left);
+        }
+      },
+      // 深度观察监听
+      deep: true,
+    },
+  },
+  //方法集合
+  methods: {
+    getCurTime(curTime) {
+      console.log(curTime);
+      this.curTime = curTime * 1000;
+    },
+    handleData() {
+      let resArr = [];
+      let leg = this.curQue.detail.length;
+      let curQue = JSON.parse(JSON.stringify(this.curQue));
+      curQue.detail.forEach((dItem, dIndex) => {
+        let paraArr = [
+          {
+            pinyin: "",
+            chs: "",
+            width: 20,
+            height: 20,
+          },
+          {
+            width: 20,
+            height: 20,
+            pinyin: "",
+            chs: "",
+          },
+        ];
+        dItem.wordsList.forEach((sItem, sIndex) => {
+          sItem.forEach((wItem, wIndex) => {
+            //this.judgePad(sItem, wItem, wIndex);
+            this.mergeWordSymbol(sItem, wItem, wIndex);
+            let obj = {
+              paraIndex: dIndex, //段落索引
+              sentIndex: sIndex, //在段落中句子索引
+              wordIndex: wIndex, //单词的索引
+              pinyin: wItem.pinyin,
+              chs: wItem.chs,
+              padding: true,
+              className: wItem.className,
+              isShow: wItem.isShow,
+              isNewWord: this.newWords.indexOf(wItem.chs) > -1 ? true : false,
+            };
+            paraArr.push(obj);
+          });
+        });
+
+        let curSentencesLeg = dItem.sentences.length;
+        let startLeg = dIndex == 0 ? 0 : curQue.detail[dIndex - 1].endLeg;
+        let endLeg = startLeg + curSentencesLeg;
+        dItem.endLeg = endLeg;
+        let timeList = curQue.wordTime.slice(startLeg, endLeg);
+        let paraObj = {
+          wordsList: paraArr,
+          timeList: timeList,
+        };
+        resArr.push(paraObj);
+      });
+      this.resArr = resArr;
+      console.log("取词模式");
+      console.log(this.resArr);
+      // 循环文章图片
+      if (curQue.img_list) {
+        curQue.img_list.forEach((item) => {
+          this.articleImg[item.imgNumber] = item.url;
+        });
+      }
+    },
+    //词和标点合一起
+    mergeWordSymbol(sItem, wItem, curIndex) {
+      let leg = sItem.length;
+      if (curIndex < leg - 1) {
+        if (this.chsFhList.indexOf(wItem.chs) > -1) {
+          wItem.isShow = false;
+        } else {
+          wItem.isShow = true;
+        }
+      }
+    },
+    //判断是否有padding
+    judgePad(sItem, wItem, curIndex) {
+      let leg = sItem.length;
+      if (curIndex < leg - 1) {
+        let nextIndex = curIndex + 1;
+        let chs = sItem[nextIndex].chs;
+        if (
+          this.chsFhList.indexOf(chs) > -1 ||
+          this.chsFhList.indexOf(wItem.chs) > -1
+        ) {
+          wItem.padding = false;
+        } else {
+          wItem.padding = true;
+        }
+        if (this.enFhList.indexOf(wItem.pinyin) > -1) {
+          wItem.className = "textLeft";
+        }
+      }
+    },
+    //转化时间
+    handleTimeList(list) {
+      let listRes = [];
+      list.forEach((item) => {
+        let res = timeStrToSen(item);
+        listRes.push(res);
+      });
+      return listRes;
+    },
+    //点击播放某个句子
+    handleChangeTime(time) {
+      this.curTime = time;
+      this.$refs.audioLine.onTimeupdateTime(time / 1000);
+    },
+    showWordDetail(e, word, pinyin) {
+      let _this = this;
+      if (_this.oldHz != word) {
+        this.isShow = false;
+        setTimeout(() => {
+          _this.hz = word;
+          _this.pinyin = pinyin;
+        }, 50);
+      }
+      _this.top = e.clientY + 20;
+      let left = e.clientX;
+      let width = 0;
+      if (word.length == 1 || word.length == 2) {
+        width = 304;
+      } else if (word.length == 3 || word.length == 4) {
+        width = 432;
+      } else if (word.length > 3) {
+        width = 560;
+      }
+      if (left - this.bodyLeft > this.contentWidth / 2) {
+        _this.left = left - width;
+      } else {
+        _this.left = left;
+      }
+    },
+    hideWordDetail() {
+      this.isShow = false;
+    },
+    changeWordCard(isShow) {
+      this.isShow = isShow;
+      this.oldHz = "";
+      this.hz = "";
+    },
+    // 处理分词数据
+    handleNewWords(val, top, left) {
+      this.isShow = true;
+      this.word = null;
+      let wordlist = val.split("");
+      let option = {
+        definition_list: [],
+        mp3_list: [],
+        new_word: val,
+        pinyin: this.pinyin,
+      };
+      this.word = { list: wordlist, detail: option, top: top, left: left };
+      //   for (let i = 0; i < this.NNPENewWordList.length; i++) {
+      //     let item = this.NNPENewWordList[i];
+      //     if (item.new_word.trim() == val.trim()) {
+      //       let wordlist = val.split("");
+      //       this.word = { list: wordlist, detail: item, top: top, left: left };
+      //       break;
+      //     }
+      //   }
+      this.oldHz = val;
+    },
+  },
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {
+    if (this.curQue) {
+      this.handleData();
+    }
+  },
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {
+    this.isShow = false;
+  }, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+.NNPE-ArticleView {
+  width: 100%;
+  .NPC-sentences-list {
+    padding: 24px 0;
+  }
+  .NNPE-detail {
+    clear: both;
+    overflow: hidden;
+    .NNPE-words {
+      float: left;
+      padding: 0 0px 8px 0px;
+      &-box {
+        float: left;
+        > span {
+          display: block;
+          &.NNPE-pinyin {
+            font-family: "GB-PINYINOK-B";
+            font-weight: normal;
+            font-size: 14px;
+            line-height: 150%;
+            color: #000000;
+            height: 21px;
+            &.textLeft {
+              text-align: left;
+            }
+          }
+          &.NNPE-chs {
+            font-family: "FZJCGFKTK";
+            font-size: 24px;
+            line-height: 150%;
+            color: #000000;
+            &.active {
+              background: rgba(60, 200, 99, 0.2);
+            }
+          }
+          &.padding {
+            padding: 0 3px;
+          }
+        }
+      }
+      &.textLeft {
+        text-align: left;
+      }
+      &.textCenter {
+        text-align: center;
+      }
+      > span {
+        display: block;
+        &.NNPE-pinyin {
+          font-family: "GB-PINYINOK-B";
+          font-weight: normal;
+          font-size: 14px;
+          line-height: 150%;
+          color: #000000;
+          height: 21px;
+          &.textLeft {
+            text-align: left;
+          }
+        }
+        &.NNPE-chs {
+          font-family: "FZJCGFKTK";
+          font-size: 24px;
+          line-height: 150%;
+          color: #000000;
+          &.active {
+            background: rgba(60, 200, 99, 0.2);
+          }
+        }
+        &.padding {
+          padding: 0 3px;
+        }
+      }
+    }
+    &.NNPE-detail-title {
+      .wordsList-box {
+        > div {
+          display: flex;
+          justify-content: center;
+        }
+      }
+    }
+    .index {
+      width: 48px;
+      box-sizing: border-box;
+      padding: 8px;
+      text-align: right;
+      border-right: 1px solid rgba(0, 0, 0, 0.1);
+      b {
+        font-weight: 400;
+        color: #000000;
+        line-height: 1.5;
+      }
+    }
+    .wordsList-box {
+      width: 100%;
+      padding: 6px 24px 12px 24px;
+      > div {
+        overflow: hidden;
+        clear: both;
+      }
+      > img {
+        width: 100%;
+        display: block;
+      }
+    }
+  }
+}
+.NNPE-wordDetail {
+  position: fixed;
+  //   width: 260px;
+  //   height: 200px;
+  //   background: #cc0;
+}
+</style>

+ 243 - 0
src/components/Adult/preview/DialogueArticleViewChs/index.vue

@@ -0,0 +1,243 @@
+<!--  -->
+<template>
+  <div class="NPC-ArticleView">
+    <div class="ArticleView-header">
+      <el-switch
+        style="display: block"
+        v-model="showPhrases"
+        active-color="#DE4444"
+        inactive-color="rgba(0,0,0,0.1)"
+        active-text=""
+        inactive-text="本课生词"
+        @change="handleSwitchChange('showPractice', 'showWord')"
+      >
+      </el-switch>
+      <el-switch
+        style="display: block"
+        v-model="showPractice"
+        active-color="#DE4444"
+        inactive-color="rgba(0,0,0,0.1)"
+        active-text=""
+        inactive-text="语音练习"
+        @change="handleSwitchChange('showPhrases', 'showWord')"
+      >
+      </el-switch>
+      <el-switch
+        style="display: block"
+        v-model="showWord"
+        active-color="#DE4444"
+        inactive-color="rgba(0,0,0,0.1)"
+        active-text=""
+        inactive-text="取词"
+        @change="handleSwitchChange('showPhrases', 'showPractice')"
+      >
+      </el-switch>
+      <!-- <div class="setting-fontsize">
+        <a @click="handleFontsize('-')"
+          ><img src="../../../../assets/newImage/common/btn-reduce.png"
+        /></a>
+        <img src="../../../../assets/newImage/common/font-size.png" />
+        <a @click="handleFontsize('+')"
+          ><img src="../../../../assets/newImage/common/btn-increase.png"
+        /></a>
+      </div> -->
+    </div>
+    <div class="ArticleView-body" ref="ArticleViewbody">
+      <NormalModelChs
+        :curQue="curQue"
+        :titleFontsize="titleFontsize"
+        :wordFontsize="wordFontsize"
+        :bodyLeft="bodyLeft"
+        :bodyWidth="bodyWidth"
+        v-if="!showPhrases && !showPractice && !showWord"
+      />
+      <PhraseModel
+        :curQue="curQue"
+        :titleFontsize="titleFontsize"
+        :wordFontsize="wordFontsize"
+        :NNPENewWordList="NNPENewWordList"
+        v-if="showPhrases"
+      />
+      <Practice
+        :curQue="curQue"
+        :titleFontsize="titleFontsize"
+        :wordFontsize="wordFontsize"
+        v-if="showPractice"
+      />
+      <WordModel
+        :curQue="curQue"
+        :titleFontsize="titleFontsize"
+        :wordFontsize="wordFontsize"
+        :bodyLeft="bodyLeft"
+        :bodyWidth="bodyWidth"
+        :NNPENewWordList="NNPENewWordList"
+        v-if="showWord"
+      />
+    </div>
+  </div>
+</template>
+
+<script>
+import PhraseModel from "./PhraseModelChs.vue";
+import NormalModelChs from "./NormalModelChs.vue";
+import Practice from "./Practicechs.vue"; // 语音练习模式
+import WordModel from "./WordModelChs.vue"; // 语音练习模式
+
+export default {
+  name: "ArticleView",
+  props: ["curQue", "NNPENewWordList"],
+  components: { NormalModelChs, Practice, WordModel, PhraseModel },
+  data() {
+    return {
+      showPreview: true, // 全文预览
+      showPhrases: false, // 显示单词和短语
+      showPractice: false, // 语音练习
+
+      showWord: false, // 取词
+      titleFontsize: 20, // 标题字号初始值
+      wordFontsize: 16, // 文章内容字号初始值
+      bodyLeft: 0,
+      bodyWidth: 0,
+      colorBox: [
+        {
+          touxiang: "#72B51D",
+          bg: "#E9F0DF",
+        },
+        {
+          touxiang: "#DE4444",
+          bg: "rgba(222, 68, 68, 0.1)",
+        },
+        {
+          touxiang: "#A7A7A7",
+          bg: "#ffffff",
+        },
+        {
+          touxiang: "#4D91F6",
+          bg: "#F1F7FF",
+        },
+        {
+          touxiang: "#FF8A00",
+          bg: "rgba(255, 138, 0, 0.1)",
+        },
+      ],
+    };
+  },
+  computed: {},
+  watch: {},
+  //方法集合
+  methods: {
+    // 处理字体大小
+    handleFontsize(symbol) {
+      if (symbol == "+") {
+        if (this.wordFontsize < 24) {
+          this.titleFontsize = this.titleFontsize + 2;
+          this.wordFontsize = this.wordFontsize + 2;
+        }
+      } else if (symbol == "-") {
+        if (this.wordFontsize > 12) {
+          this.titleFontsize = this.titleFontsize - 2;
+          this.wordFontsize = this.wordFontsize - 2;
+        }
+      }
+    },
+    // 切换开关
+    handleSwitchChange(obj1, obj2) {
+      this[obj1] = false;
+      this[obj2] = false;
+      this.showPreview = false;
+    },
+  },
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {
+    console.log("我是文章预览");
+    console.log(this.curQue);
+    this.$nextTick(() => {
+      this.bodyLeft = this.$refs.ArticleViewbody.getBoundingClientRect().left;
+    });
+    console.log(this.NNPENewWordList);
+  },
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+.NPC-ArticleView {
+  width: 100%;
+  .ArticleView-header {
+    display: flex;
+    justify-content: flex-end;
+    align-items: center;
+    margin-bottom: 16px;
+    .setting-fontsize {
+      display: flex;
+      margin-left: 24px;
+      a {
+        border: 1px solid rgba(0, 0, 0, 0.1);
+        box-sizing: border-box;
+        border-radius: 4px;
+        display: block;
+        height: 24px;
+        width: 24px;
+      }
+      img {
+        width: 100%;
+      }
+      > img {
+        margin: 0 8px;
+        width: 24px;
+      }
+    }
+  }
+  .ArticleView-body {
+    border: 1px solid rgba(0, 0, 0, 0.1);
+    box-sizing: border-box;
+    border-radius: 8px;
+    overflow: hidden;
+    background: #fff;
+    box-sizing: border-box;
+    .aduioLine-box {
+      border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+      width: 100%;
+    }
+  }
+}
+</style>
+<style lang="scss">
+.NPC-ArticleView {
+  .ArticleView-header {
+    .el-switch {
+      margin-left: 24px;
+    }
+    .el-switch__core {
+      width: 44px !important;
+      height: 24px;
+      border-radius: 20px;
+    }
+    .el-switch__core:after {
+      top: 3px;
+      left: 3px;
+    }
+    .el-switch.is-checked .el-switch__core::after {
+      left: 100%;
+      margin-left: -19px;
+    }
+    .el-switch__label {
+      color: #000000;
+    }
+    .el-switch__label.is-active {
+      color: rgba($color: #000000, $alpha: 0.3);
+    }
+    .el-switch__label--left {
+      margin-right: 8px;
+    }
+  }
+}
+</style>

+ 7 - 0
src/styles/index.scss

@@ -227,10 +227,17 @@ input:-ms-input-placeholder {
         text-align: right;
         margin-right: 8px;
         line-height: 32px;
+        &-bottom{
+          margin-bottom:10px;
+          display: block;
+        }
     }
     .adult-book-input {
         width: 500px;
         margin-right: 10px;
+        &-800{
+          width: 800px;
+        }
     }
     .el-radio-group {
         padding: 8px 0;

+ 2 - 1
src/views/adultInput.vue

@@ -174,7 +174,8 @@
                         topicIitem.type == 'inputItem_chs' ||
                         topicIitem.type == 'sentence_input_chs' ||
                         topicIitem.type == 'sentence_judge_chs' ||
-                        topicIitem.type == 'sentence_record_chs'
+                        topicIitem.type == 'sentence_record_chs' ||
+                        topicIitem.type == 'sentence_input_record_chs'
                       "
                     >
                       <template v-if="topicIitem.is_edit">