Browse Source

气泡编辑

natasha 4 days ago
parent
commit
f91a0ad5f1

+ 1 - 0
src/icons/svg/change.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1778334459749" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1668" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M128 512c0 212.074667 171.925333 384 384 384s384-171.925333 384-384S724.074667 128 512 128 128 299.925333 128 512z m38.4 0c0-190.869333 154.730667-345.6 345.6-345.6S857.6 321.130667 857.6 512 702.869333 857.6 512 857.6 166.4 702.869333 166.4 512z" fill="#000000" p-id="1669"></path><path d="M575.232 364.032a19.2 19.2 0 0 1 27.136 0l76.8 76.8A19.2 19.2 0 0 1 665.6 473.6H339.2a19.2 19.2 0 0 1 0-38.4h280.042667l-44.010667-44.032a19.2 19.2 0 0 1 0-27.136zM429.568 659.968a19.2 19.2 0 0 1-27.136 0l-76.8-76.8A19.2 19.2 0 0 1 339.2 550.4h326.4a19.2 19.2 0 0 1 0 38.4H385.557333l44.010667 44.032a19.2 19.2 0 0 1 0 27.136z" fill="#000000" p-id="1670"></path></svg>

+ 251 - 43
src/views/book/courseware/create/components/question/article/Article.vue

@@ -103,6 +103,61 @@
           />
         </div>
       </div>
+      <template v-if="data.detail.length > 0">
+        <el-divider content-position="left"
+          >预览效果<el-button
+            v-show="data.detail.length > 0"
+            type="text"
+            icon="el-icon-refresh"
+            title="刷新"
+            class="refresh-pinyin-btn"
+            @click.native="handleChangeContent"
+        /></el-divider>
+        <div v-for="(item, index) in data.detail" :key="index" class="text">
+          <template v-for="(witem, windex) in item.wordsList">
+            <div
+              v-for="(wItem, wIndex) in witem"
+              :key="windex + '-' + wIndex"
+              class="text-item"
+              :style="{
+                textAlign: windex === 0 && wIndex === 0 ? 'left' : '',
+              }"
+            >
+              <span
+                class="pinyin"
+                :style="{
+                  fontSize: articleAttrib.pinyin_size,
+                }"
+                v-if="isEnable(data.property.view_pinyin)"
+                @click="selectItem(wItem)"
+                >{{
+                  windex === 0 &&
+                  wIndex === 0 &&
+                  data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case === 'true'
+                    ? wItem.pinyin_up
+                    : wItem.pinyin
+                }}</span
+              >
+              <span
+                class="word"
+                :style="{
+                  fontFamily: wItem.fontFamily,
+                  textDecoration: wItem.textDecoration,
+                  borderBottom: wItem.border === 'dotted' ? '1px dotted' : '',
+                  fontWeight: wItem.fontWeight,
+                  color:
+                    wItem.matchNotesObj.con && wItem.matchNotesObj.notesColor
+                      ? wItem.matchNotesObj.notesColor
+                      : wItem.color,
+                  fontSize: articleAttrib.font_size,
+                }"
+                @click="matchItemNotes(wItem)"
+                >{{ wItem.chs }}</span
+              >
+            </div>
+          </template>
+        </div>
+      </template>
       <el-dialog
         v-if="dialogFlag"
         :visible.sync="dialogFlag"
@@ -201,6 +256,7 @@
           :data-notes="data.notes_list"
           :unified-attrib="data.unified_attrib ? data.unified_attrib : null"
           @sureNotes="sureNotes"
+          @handleSyncCon="handleSyncCon"
         />
         <NewWord
           v-if="editWordIndex === 2"
@@ -210,49 +266,6 @@
         />
       </template>
 
-      <template v-if="isEnable(data.property.view_pinyin)">
-        <el-divider content-position="left"
-          >拼音效果<el-button
-            v-show="isEnable(data.property.view_pinyin)"
-            type="text"
-            icon="el-icon-refresh"
-            title="刷新"
-            class="refresh-pinyin-btn"
-            @click.native="handleChangeContent"
-        /></el-divider>
-        <div v-for="(item, index) in data.detail" :key="index" class="text">
-          <template v-for="(witem, windex) in item.wordsList">
-            <div
-              v-for="(wItem, wIndex) in witem"
-              :key="windex + '-' + wIndex"
-              class="text-item"
-              :style="{
-                textAlign: windex === 0 && wIndex === 0 ? 'left' : '',
-              }"
-              @click="selectItem(wItem)"
-            >
-              <span class="pinyin">{{
-                windex === 0 &&
-                wIndex === 0 &&
-                data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case === 'true'
-                  ? wItem.pinyin_up
-                  : wItem.pinyin
-              }}</span>
-              <span
-                class="word"
-                :style="{
-                  fontFamily: wItem.fontFamily,
-                  textDecoration: wItem.textDecoration,
-                  borderBottom: wItem.border === 'dotted' ? '1px dotted' : '',
-                  fontWeight: wItem.fontWeight,
-                  color: wItem.color,
-                }"
-                >{{ wItem.chs }}</span
-              >
-            </div>
-          </template>
-        </div>
-      </template>
       <!-- </el-dialog> -->
       <!-- 添加图片 -->
       <el-dialog
@@ -275,6 +288,41 @@
         :option-list="subtitleList"
         @saveSubtitles="saveSubtitles"
       />
+      <!-- 关联注释 -->
+      <el-dialog
+        v-if="matchNoteFlag"
+        :visible.sync="matchNoteFlag"
+        :show-close="true"
+        :close-on-click-modal="false"
+        :modal-append-to-body="false"
+        :modal="false"
+        width="600px"
+        class="article-matchNotes-dialog"
+        :title="matchNotesObj.id ? '编辑气泡' : '添加气泡'"
+      >
+        <div class="matchNotes-box">
+          <RichText
+            v-if="matchNotesObj.isRich"
+            ref="richText"
+            v-model="matchNotesObj.con"
+            :font-size="data.unified_attrib?.font_size"
+            :font-family="data.unified_attrib?.font"
+            :font-color="data.unified_attrib?.text_color"
+            toolbar="fontselect fontsizeselect forecolor backcolor | underline | bold italic strikethrough alignleft aligncenter alignright image media link"
+          />
+          <el-input v-else v-model="matchNotesObj.con" type="textarea" rows="5"></el-input>
+          <div class="matchNotes-color">
+            <span>气泡颜色<el-color-picker v-model="matchNotesObj.notesColor"></el-color-picker></span>
+            <span @click="matchNotesObj.isRich = !matchNotesObj.isRich"
+              ><SvgIcon icon-class="change" size="16" />切换文本模式</span
+            >
+          </div>
+          <div class="btn-box">
+            <el-button type="info" size="small" @click="cancleMatchNotesDialog">删除</el-button>
+            <el-button type="primary" size="small" @click="sureMatchNotes">保存</el-button>
+          </div>
+        </div>
+      </el-dialog>
     </template>
   </ModuleBase>
 </template>
@@ -305,6 +353,8 @@ import {
 const Base64 = require('js-base64').Base64;
 import cnchar from 'cnchar';
 import { toolGetWordPinyinCorrectionList } from '@/api/pinyinCorrection';
+import { PinyinBuild_OldFormat } from '@/api/book';
+import { getRandomNumber } from '@/utils';
 
 export default {
   name: 'ArticlePage',
@@ -361,6 +411,8 @@ export default {
       ],
       pinyinList: [], // 拼音校正列表
       articleAttrib: null,
+      matchNoteItem: null, // 选中关联注释的词
+      matchNoteFlag: false,
     };
   },
   watch: {
@@ -605,6 +657,16 @@ export default {
             notesColor: '',
             img: [],
             imgPosition: 'after',
+            matchNotesObj: {
+              number: '',
+              con: '',
+              pinyin: '',
+              interpret: '',
+              note: '',
+              notesColor: '#8206BF',
+              id: '',
+              isRich: true,
+            },
           };
           sentArr.push(obj);
         });
@@ -698,6 +760,16 @@ export default {
                   notesColor: '',
                   img: [],
                   imgPosition: 'after',
+                  matchNotesObj: {
+                    number: '',
+                    con: '',
+                    pinyin: '',
+                    interpret: '',
+                    note: '',
+                    notesColor: '#8206BF',
+                    id: '',
+                    isRich: true,
+                  },
                 };
                 sentArr.push(obj);
               });
@@ -1239,6 +1311,97 @@ export default {
         });
       }
     },
+    // 点击汉字打开关联注释弹窗
+    matchItemNotes(item) {
+      if (!item.matchNotesObj.id) {
+        item.matchNotesObj.id = getRandomNumber();
+      }
+      this.matchNotesObj = item.matchNotesObj;
+      this.matchNoteFlag = true;
+    },
+    cancleMatchNotesDialog() {
+      this.$confirm('确定要删除此条气泡吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning',
+      })
+        .then(() => {
+          this.handleSyncCon(this.matchNotesObj, 'delete');
+          this.matchNoteFlag = false;
+        })
+        .catch(() => {});
+    },
+    // 确定关联注释
+    sureMatchNotes() {
+      let index = this.data.notes_list.option.findIndex((items) => items.id === this.matchNotesObj.id);
+      if (index > -1) {
+        this.data.notes_list.option[index] = this.matchNotesObj;
+      } else {
+        this.data.notes_list.option.push(this.matchNotesObj);
+      }
+      this.matchNoteFlag = false;
+      this.editWordsFlag = true;
+      this.editWordIndex = 1;
+    },
+    async handleBlurCon() {
+      let text = this.matchNotesObj.con.replace(/<[^>]+>/g, '');
+      if (text) {
+        this.matchNotesObj.pinyin = await this.handlePinyins(
+          text,
+          this.data.notes_list.property.is_first_sentence_first_hz_pinyin_first_char_upper_case,
+        );
+      }
+    },
+    // 自动生成拼音
+    handlePinyins(text, flag) {
+      let data = {
+        text: text,
+        is_rich_text: 'false',
+        is_first_sentence_first_hz_pinyin_first_char_upper_case: flag ? flag : 'false',
+        is_fill_space: 'false',
+        is_custom_fc: 'false',
+      };
+      return new Promise((resolve, reject) => {
+        PinyinBuild_OldFormat(data).then((res) => {
+          if (res.parsed_text) {
+            let mergedData = '';
+            res.parsed_text.paragraph_list.map((outerArr, i) =>
+              outerArr.map((innerArr, j) =>
+                innerArr.map((newItem, k) => {
+                  mergedData += newItem.pinyin + ' ';
+                }),
+              ),
+            );
+            resolve(mergedData);
+          }
+        });
+      });
+    },
+    // 在气泡列表里修改了内容,同步detail的内容
+    handleSyncCon(obj, type) {
+      this.data.detail.forEach((item) => {
+        item.wordsList.forEach((items) => {
+          items.forEach((itemss) => {
+            if (itemss.matchNotesObj.id === obj.id) {
+              if (type === 'delete') {
+                itemss.matchNotesObj = {
+                  number: '',
+                  con: '',
+                  pinyin: '',
+                  interpret: '',
+                  note: '',
+                  notesColor: '#8206BF',
+                  id: '',
+                  isRich: true,
+                };
+              } else {
+                itemss.matchNotesObj = obj;
+              }
+            }
+          });
+        });
+      });
+    },
   },
 };
 </script>
@@ -1334,6 +1497,7 @@ export default {
   .text-item {
     padding: 0 1px;
     text-align: center;
+    cursor: pointer;
   }
 
   .pinyin {
@@ -1379,6 +1543,50 @@ export default {
 }
 </style>
 <style lang="scss">
+.article-matchNotes-dialog {
+  .el-dialog__header,
+  .el-dialog__body {
+    padding: 5px 10px;
+  }
+
+  .btn-box {
+    display: block;
+    padding: 5px 0;
+    text-align: right;
+
+    .el-button {
+      padding: 2px 12px;
+      font-size: 12px;
+      line-height: 20px;
+    }
+  }
+
+  .matchNotes-color {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    margin-top: 5px;
+
+    span {
+      display: flex;
+      gap: 3px;
+      align-items: center;
+      cursor: pointer;
+    }
+
+    .el-color-picker--small {
+      height: 16px;
+    }
+
+    .el-color-picker__trigger {
+      width: 16px;
+      height: 16px;
+      padding: 0;
+      border: none;
+    }
+  }
+}
+
 .article-checkpinyin-dialog {
   .el-dialog__header {
     padding: 0;

+ 2 - 2
src/views/book/courseware/create/components/question/article/CheckStyle.vue

@@ -111,7 +111,7 @@
             @blur="onBlur(itemActive, 'matchWords')"
           ></el-input>
         </div>
-        <div class="match-info" v-if="batchList.length < 2">
+        <!-- <div class="match-info" v-if="batchList.length < 2">
           <label>关联注释:</label>
           <el-input
             v-model="itemActive.matchNotes"
@@ -119,7 +119,7 @@
             @blur="onBlur(itemActive, 'matchNotes')"
           ></el-input>
           <el-color-picker v-model="itemActive.notesColor"></el-color-picker>
-        </div>
+        </div> -->
         <div class="btn-box">
           <el-button type="info" size="small" @click="cancleDialog">取消</el-button>
           <el-button type="primary" size="small" @click="surePinyin">保存</el-button>

+ 3 - 0
src/views/book/courseware/create/components/question/article/NewWord.vue

@@ -331,6 +331,9 @@
           </el-radio>
         </el-radio-group>
       </el-form-item>
+      <el-form-item label="预览展示">
+        <el-switch v-model="data.property.is_show" active-value="true" inactive-value="false" />
+      </el-form-item>
     </el-form>
     <!-- <div class="btn-box" style="text-align: right">
       <el-button @click="sureNewWords">保存</el-button>

+ 83 - 25
src/views/book/courseware/create/components/question/article/Notes.vue

@@ -14,12 +14,12 @@
       :font-color="unifiedAttrib?.text_color"
     />
     <el-table :data="data.option" border style="width: 100%">
-      <el-table-column fixed prop="number" label="序号" width="70">
+      <!-- <el-table-column fixed prop="number" label="序号" width="70">
         <template slot-scope="scope">
           <el-input v-model="scope.row.number" />
         </template>
-      </el-table-column>
-      <el-table-column fixed prop="con" label="内容" width="200">
+      </el-table-column> -->
+      <el-table-column fixed prop="con" label="内容">
         <template slot-scope="scope">
           <RichText
             v-if="property.isGetContent"
@@ -35,7 +35,7 @@
           />
         </template>
       </el-table-column>
-      <el-table-column v-if="isEnable(data.property.view_pinyin)" prop="con" label="拼音" width="150">
+      <!-- <el-table-column v-if="isEnable(data.property.view_pinyin)" prop="con" label="拼音" width="150">
         <template slot-scope="scope">
           <RichText
             v-if="property.isGetContent"
@@ -76,7 +76,7 @@
             :font-color="unifiedAttrib?.text_color"
           />
         </template>
-      </el-table-column>
+      </el-table-column> -->
       <!-- <el-table-column prop="img_list" label="图片" width="300">
         <template slot-scope="scope">
           <UploadPicture
@@ -90,7 +90,7 @@
       </el-table-column> -->
       <el-table-column prop="notesColor" label="在课文中的颜色" width="130">
         <template slot-scope="scope">
-          <el-color-picker v-model="scope.row.notesColor"></el-color-picker>
+          <el-color-picker v-model="scope.row.notesColor" @change="handleChangeColor(scope.$index)"></el-color-picker>
         </template>
       </el-table-column>
       <el-table-column label="操作" width="150">
@@ -103,7 +103,7 @@
     </el-table>
     <!-- <el-button icon="el-icon-plus" style="margin: 24px 0" @click="addElement">增加一个</el-button> -->
     <el-form :model="data.property" label-width="72px" label-position="left" style="margin: 24px 0">
-      <el-form-item label="拼音">
+      <!-- <el-form-item label="拼音">
         <el-switch v-model="data.property.view_pinyin" active-value="true" inactive-value="false" />
       </el-form-item>
       <el-form-item label="拼音位置">
@@ -125,6 +125,9 @@
           false-label="false"
           >句首大写</el-checkbox
         >
+      </el-form-item> -->
+      <el-form-item label="预览展示">
+        <el-switch v-model="data.property.is_show" active-value="true" inactive-value="false" />
       </el-form-item>
     </el-form>
   </div>
@@ -136,6 +139,7 @@ import RichText from '@/components/RichText.vue';
 import UploadPicture from '../new_word/components/UploadPicture.vue';
 import { pinyinPositionLists } from '@/views/book/courseware/data/notes';
 import { isEnable } from '@/views/book/courseware/data/common';
+import { PinyinBuild_OldFormat } from '@/api/book';
 export default {
   name: 'NotesPage',
   components: {
@@ -166,7 +170,16 @@ export default {
   methods: {
     // 删除行
     handleDelete(index) {
-      this.data.option.splice(index, 1);
+      this.$confirm('确定要删除此条气泡吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning',
+      })
+        .then(() => {
+          this.$emit('handleSyncCon', this.data.option[index], 'delete');
+          this.data.option.splice(index, 1);
+        })
+        .catch(() => {});
     },
     // 上移下移
     moveElement(dItem, index, type) {
@@ -204,28 +217,73 @@ export default {
       this.data.option[index].file_list[0] = '';
       this.data.file_id_list = this.data.file_id_list.filter((item) => item !== file_id);
     },
-    handleBlurCon(i) {
+    async handleBlurCon(i) {
       let text = this.data.option[i].con.replace(/<[^>]+>/g, '');
-      this.data.option[i].pinyin = cnchar
-        .spell(
+      if (text) {
+        this.data.option[i].pinyin = await this.handlePinyins(
           text,
-          'array',
-          this.data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case === 'true' ? 'high' : 'low',
-          'tone',
-        )
-        .join(' ');
+          this.data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case,
+        );
+      }
+      this.$emit('handleSyncCon', this.data.option[i]);
+      // this.data.option[i].pinyin = cnchar
+      //   .spell(
+      //     text,
+      //     'array',
+      //     this.data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case === 'true' ? 'high' : 'low',
+      //     'tone',
+      //   )
+      //   .join(' ');
+    },
+    handleChangeColor(i) {
+      this.$emit('handleSyncCon', this.data.option[i]);
     },
-    handlePinyin() {
-      this.data.option.forEach((item) => {
+    async handlePinyin() {
+      for (const item of this.data.option) {
         let text = item.con.replace(/<[^>]+>/g, '');
-        item.pinyin = cnchar
-          .spell(
+        if (text) {
+          item.pinyin = await this.handlePinyins(
             text,
-            'array',
-            this.data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case === 'true' ? 'high' : 'low',
-            'tone',
-          )
-          .join(' ');
+            this.data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case,
+          );
+        }
+      }
+      // this.data.option.forEach((item) => {
+      //   let text = item.con.replace(/<[^>]+>/g, '');
+
+      // item.pinyin = cnchar
+      //   .spell(
+      //     text,
+      //     'array',
+      //     this.data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case === 'true' ? 'high' : 'low',
+      //     'tone',
+      //   )
+      //   .join(' ');
+      // });
+    },
+    // 自动生成拼音
+    handlePinyins(text, flag) {
+      let data = {
+        text: text,
+        is_rich_text: 'false',
+        is_first_sentence_first_hz_pinyin_first_char_upper_case: flag ? flag : 'false',
+        is_fill_space: 'false',
+        is_custom_fc: 'false',
+      };
+      return new Promise((resolve, reject) => {
+        PinyinBuild_OldFormat(data).then((res) => {
+          if (res.parsed_text) {
+            let mergedData = '';
+            res.parsed_text.paragraph_list.map((outerArr, i) =>
+              outerArr.map((innerArr, j) =>
+                innerArr.map((newItem, k) => {
+                  mergedData += newItem.pinyin + ' ';
+                }),
+              ),
+            );
+            resolve(mergedData);
+          }
+        });
       });
     },
   },

+ 3 - 0
src/views/book/courseware/data/article.js

@@ -108,6 +108,7 @@ export function getArticleData() {
         voice_type: '', // 音色
         emotion: '', // 风格,情感
         speed_ratio: '', // 语速
+        is_show: 'false',
       },
       new_word_list: [],
       lrc_arr: [], // lrc 文件解析后的数据
@@ -162,6 +163,7 @@ export function getArticleData() {
         voice_type: '', // 音色
         emotion: '', // 风格,情感
         speed_ratio: '', // 语速
+        is_show: 'false',
       },
       new_word_list: [],
       lrc_arr: [], // lrc 文件解析后的数据
@@ -215,6 +217,7 @@ export function getArticleData() {
         view_pinyin: 'false', // 显示拼音
         pinyin_position: pinyinPositionLists[1].value, // top bottom
         is_first_sentence_first_hz_pinyin_first_char_upper_case: 'true', // 句首大写
+        is_show: 'false',
       },
     },
     sentence_list_mp: [], // 句子+分词数组

+ 3 - 0
src/views/book/courseware/data/dialogueArticle.js

@@ -151,6 +151,7 @@ export function getArticleData() {
         voice_type: '', // 音色
         emotion: '', // 风格,情感
         speed_ratio: '', // 语速
+        is_show: 'false',
       },
       new_word_list: [],
       lrc_arr: [], // lrc 文件解析后的数据
@@ -205,6 +206,7 @@ export function getArticleData() {
         voice_type: '', // 音色
         emotion: '', // 风格,情感
         speed_ratio: '', // 语速
+        is_show: 'false',
       },
       new_word_list: [],
       lrc_arr: [], // lrc 文件解析后的数据
@@ -258,6 +260,7 @@ export function getArticleData() {
         view_pinyin: 'false', // 显示拼音
         pinyin_position: pinyinPositionLists[1].value, // top bottom
         is_first_sentence_first_hz_pinyin_first_char_upper_case: 'true', // 句首大写
+        is_show: 'false',
       },
     },
     sentence_list_mp: [], // 句子+分词数组

+ 27 - 32
src/views/book/courseware/preview/components/article/NormalModelChs.vue

@@ -76,7 +76,9 @@
                   'article-content',
                   isHasRemark ? 'hasRemark' : '',
                 ]"
-                :style="{ width: curQue.property.remarkWidth ? 100 - curQue.property.remarkWidth * 1 + '%' : '' }"
+                :style="{
+                  width: isHasRemark && curQue.property.remarkWidth ? 100 - curQue.property.remarkWidth * 1 + '%' : '',
+                }"
               >
                 <template v-if="item.sourceList.length > 0 && item.sourcePosition === 'before'">
                   <img
@@ -206,13 +208,9 @@
                                       curTime < item.timeList[pItem.sentIndex].ed &&
                                       attrib
                                         ? attrib.topic_color
-                                        : pItem.notesColor
-                                          ? pItem.notesColor
-                                          : annotationList.indexOf(pItem.chs) > -1
-                                            ? NNPEAnnotationList.find(
-                                                (item) => item.con.replace(/<[^>]*>?/gm, '') === pItem.chs,
-                                              ).notesColor
-                                            : pItem.config.color,
+                                        : pItem.matchNotesObj.con && pItem.matchNotesObj.notesColor
+                                          ? pItem.matchNotesObj.notesColor
+                                          : pItem.config.color,
                                   }"
                                   @click.stop="
                                     viewNotes(
@@ -345,14 +343,10 @@
                                   curTime <= item.timeList[pItem.sentIndex].ed &&
                                   attrib
                                     ? attrib.topic_color
-                                    : item.wordsList[pIndex + 1].notesColor
-                                      ? item.wordsList[pIndex + 1].notesColor
-                                      : annotationList.indexOf(item.wordsList[pIndex + 1].chs) > -1
-                                        ? NNPEAnnotationList.find(
-                                            (item) =>
-                                              item.con.replace(/<[^>]*>?/gm, '') === item.wordsList[pIndex + 1].chs,
-                                          ).notesColor
-                                        : item.wordsList[pIndex + 1].config.color,
+                                    : item.wordsList[pIndex + 1].matchNotesObj.con &&
+                                        item.wordsList[pIndex + 1].matchNotesObj.notesColor
+                                      ? item.wordsList[pIndex + 1].matchNotesObj.notesColor
+                                      : item.wordsList[pIndex + 1].config.color,
                               }"
                               @click.stop="
                                 viewNotes(
@@ -494,14 +488,10 @@
                                   curTime <= item.timeList[pItem.sentIndex].ed &&
                                   attrib
                                     ? attrib.topic_color
-                                    : item.wordsList[pIndex + 2].notesColor
-                                      ? item.wordsList[pIndex + 2].notesColor
-                                      : annotationList.indexOf(item.wordsList[pIndex + 2].chs) > -1
-                                        ? NNPEAnnotationList.find(
-                                            (item) =>
-                                              item.con.replace(/<[^>]*>?/gm, '') === item.wordsList[pIndex + 2].chs,
-                                          ).notesColor
-                                        : item.wordsList[pIndex + 2].config.color,
+                                    : item.wordsList[pIndex + 1].matchNotesObj.con &&
+                                        item.wordsList[pIndex + 1].matchNotesObj.notesColor
+                                      ? item.wordsList[pIndex + 2].matchNotesObj.notesColor
+                                      : item.wordsList[pIndex + 2].config.color,
                               }"
                               @click.stop="
                                 viewNotes(
@@ -643,13 +633,9 @@
                                     curTime < item.timeList[pItem.sentIndex].ed &&
                                     attrib
                                       ? attrib.topic_color
-                                      : pItem.notesColor
-                                        ? pItem.notesColor
-                                        : annotationList.indexOf(pItem.chs) > -1
-                                          ? NNPEAnnotationList.find(
-                                              (item) => item.con.replace(/<[^>]*>?/gm, '') === pItem.chs,
-                                            ).notesColor
-                                          : pItem.config.color,
+                                      : pItem.matchNotesObj.con && pItem.matchNotesObj.notesColor
+                                        ? pItem.matchNotesObj.notesColor
+                                        : pItem.config.color,
                                 }"
                                 @click.stop="
                                   viewNotes(
@@ -746,7 +732,15 @@
                   ></video>
                 </template>
               </div>
-              <div v-if="item.remarkDetail" :class="['remarkBox', 'remark-top-8']">
+              <div
+                v-if="
+                  item.remarkDetail &&
+                  (item.remarkDetail.chs ||
+                    item.remarkDetail.en ||
+                    (item.remarkDetail.img_list && item.remarkDetail.img_list.length > 0))
+                "
+                :class="['remarkBox', 'remark-top-8']"
+              >
                 <RemarkChs :remark-detail="item.remarkDetail" :margin-top="8" />
               </div>
             </div>
@@ -1584,6 +1578,7 @@ export default {
               matchWords: wItem.matchWords,
               matchNotes: wItem.matchNotes,
               notesColor: wItem.notesColor,
+              matchNotesObj: wItem.matchNotesObj,
               img: wItem.img,
               imgPosition: wItem.imgPosition,
             };

+ 22 - 31
src/views/book/courseware/preview/components/article/PhraseModelChs.vue

@@ -78,7 +78,9 @@
                   'article-content',
                   isHasRemark ? 'hasRemark' : '',
                 ]"
-                :style="{ width: curQue.property.remarkWidth ? 100 - curQue.property.remarkWidth * 1 + '%' : '' }"
+                :style="{
+                  width: isHasRemark && curQue.property.remarkWidth ? 100 - curQue.property.remarkWidth * 1 + '%' : '',
+                }"
               >
                 <template v-if="item.sourceList.length > 0 && item.sourcePosition === 'before'">
                   <img
@@ -158,8 +160,8 @@
                                     ? attrib
                                       ? attrib.topic_color
                                       : pItem.config.color
-                                    : pItem.notesColor
-                                      ? pItem.notesColor
+                                    : pItem.matchNotesObj.con && pItem.matchNotesObj.notesColor
+                                      ? pItem.matchNotesObj.notesColor
                                       : pItem.config.color,
                               }"
                               ><span
@@ -181,13 +183,9 @@
                                     curTime < item.timeList[pItem.sentIndex].ed &&
                                     attrib
                                       ? attrib.topic_color
-                                      : pItem.notesColor
-                                        ? pItem.notesColor
-                                        : annotationList.indexOf(pItem.chs) > -1
-                                          ? NNPEAnnotationList.find(
-                                              (item) => item.con.replace(/<[^>]*>?/gm, '') === pItem.chs,
-                                            ).notesColor
-                                          : pItem.config.color,
+                                      : pItem.matchNotesObj.con && pItem.matchNotesObj.notesColor
+                                        ? pItem.matchNotesObj.notesColor
+                                        : pItem.config.color,
                                 }"
                                 @click.stop="viewNotes($event, pItem.chs[wIndex], pItem.chs, pItem)"
                                 >{{ convertText(pItem.chs[wIndex]) }}</span
@@ -248,12 +246,10 @@
                                 textDecoration: item.wordsList[pIndex + 1].config.textDecoration,
                                 borderBottom: item.wordsList[pIndex + 1].config.border === 'dotted' ? '1px dotted' : '',
                                 fontWeight: item.wordsList[pIndex + 1].config.fontWeight,
-                                color: item.wordsList[pIndex + 1].notesColor
-                                  ? item.wordsList[pIndex + 1].notesColor
-                                  : annotationList.indexOf(item.wordsList[pIndex + 1].chs) > -1
-                                    ? NNPEAnnotationList.find(
-                                        (item) => item.con.replace(/<[^>]*>?/gm, '') === item.wordsList[pIndex + 1].chs,
-                                      ).notesColor
+                                color:
+                                  item.wordsList[pIndex + 1].matchNotesObj.con &&
+                                  item.wordsList[pIndex + 1].matchNotesObj.notesColor
+                                    ? item.wordsList[pIndex + 1].matchNotesObj.notesColor
                                     : item.wordsList[pIndex + 1].config.color,
                                 height:
                                   attrib && attrib.font_size ? attrib.font_size.replace('pt', '') * 1.4 + 'pt' : '28px',
@@ -348,12 +344,10 @@
                                 textDecoration: item.wordsList[pIndex + 2].config.textDecoration,
                                 borderBottom: item.wordsList[pIndex + 2].config.border === 'dotted' ? '1px dotted' : '',
                                 fontWeight: item.wordsList[pIndex + 2].config.fontWeight,
-                                color: item.wordsList[pIndex + 2].notesColor
-                                  ? item.wordsList[pIndex + 2].notesColor
-                                  : annotationList.indexOf(item.wordsList[pIndex + 2].chs) > -1
-                                    ? NNPEAnnotationList.find(
-                                        (item) => item.con.replace(/<[^>]*>?/gm, '') === item.wordsList[pIndex + 2].chs,
-                                      ).notesColor
+                                color:
+                                  item.wordsList[pIndex + 2].matchNotesObj.con &&
+                                  item.wordsList[pIndex + 2].matchNotesObj.notesColor
+                                    ? item.wordsList[pIndex + 2].matchNotesObj.notesColor
                                     : item.wordsList[pIndex + 2].config.color,
                                 height:
                                   attrib && attrib.font_size ? attrib.font_size.replace('pt', '') * 1.4 + 'pt' : '28px',
@@ -449,8 +443,8 @@
                                   ? attrib
                                     ? attrib.topic_color
                                     : pItem.config.color
-                                  : pItem.notesColor
-                                    ? pItem.notesColor
+                                  : pItem.matchNotesObj.con && pItem.matchNotesObj.notesColor
+                                    ? pItem.matchNotesObj.notesColor
                                     : pItem.config.color,
                             }"
                             ><span
@@ -472,13 +466,9 @@
                                   curTime < item.timeList[pItem.sentIndex].ed &&
                                   attrib
                                     ? attrib.topic_color
-                                    : pItem.notesColor
-                                      ? pItem.notesColor
-                                      : annotationList.indexOf(pItem.chs) > -1
-                                        ? NNPEAnnotationList.find(
-                                            (item) => item.con.replace(/<[^>]*>?/gm, '') === pItem.chs,
-                                          ).notesColor
-                                        : pItem.config.color,
+                                    : pItem.matchNotesObj.con && pItem.matchNotesObj.notesColor
+                                      ? pItem.matchNotesObj.notesColor
+                                      : pItem.config.color,
                               }"
                               @click.stop="viewNotes($event, pItem.chs[wIndex], pItem.chs, pItem)"
                               >{{ convertText(pItem.chs[wIndex]) }}</span
@@ -1323,6 +1313,7 @@ export default {
               matchWords: wItem.matchWords,
               matchNotes: wItem.matchNotes,
               notesColor: wItem.notesColor,
+              matchNotesObj: wItem.matchNotesObj,
               img: wItem.img,
               imgPosition: wItem.imgPosition,
             };

+ 1 - 0
src/views/book/courseware/preview/components/article/Practicechs.vue

@@ -973,6 +973,7 @@ export default {
               matchWords: wItem.matchWords,
               matchNotes: wItem.matchNotes,
               notesColor: wItem.notesColor,
+              matchNotesObj: wItem.matchNotesObj,
               img: wItem.img,
               imgPosition: wItem.imgPosition,
             };

+ 1 - 0
src/views/book/courseware/preview/components/article/WordModelChs.vue

@@ -1136,6 +1136,7 @@ export default {
               matchWords: wItem.matchWords,
               matchNotes: wItem.matchNotes,
               notesColor: wItem.notesColor,
+              matchNotesObj: wItem.matchNotesObj,
               img: wItem.img,
               imgPosition: wItem.imgPosition,
             };

+ 19 - 3
src/views/book/courseware/preview/components/article/index.vue

@@ -215,18 +215,33 @@
         </div>
       </div>
       <template
-        v-if="data.new_word_list && data.new_word_list.new_word_list && data.new_word_list.new_word_list.length > 0"
+        v-if="
+          data.new_word_list &&
+          data.new_word_list.new_word_list &&
+          data.new_word_list.new_word_list.length > 0 &&
+          data.new_word_list.property.is_show === 'true'
+        "
       >
         <NewWordPreview :new-data="data.new_word_list" :is-mobile="isMobile" />
       </template>
       <template
         v-if="
-          data.other_word_list && data.other_word_list.new_word_list && data.other_word_list.new_word_list.length > 0
+          data.other_word_list &&
+          data.other_word_list.new_word_list &&
+          data.other_word_list.new_word_list.length > 0 &&
+          data.other_word_list.property.is_show === 'true'
         "
       >
         <NewWordPreview :new-data="data.other_word_list" :is-mobile="isMobile" />
       </template>
-      <template v-if="data.notes_list && data.notes_list.option && data.notes_list.option.length > 0">
+      <template
+        v-if="
+          data.notes_list &&
+          data.notes_list.option &&
+          data.notes_list.option.length > 0 &&
+          data.notes_list.property.is_show === 'true'
+        "
+      >
         <NotesPreview :notes-data="data.notes_list" :is-mobile="isMobile" />
       </template>
     </div>
@@ -594,6 +609,7 @@ export default {
               matchWords: wItem.matchWords,
               matchNotes: wItem.matchNotes,
               notesColor: wItem.notesColor,
+              matchNotesObj: wItem.matchNotesObj,
               img: wItem.img,
               imgPosition: wItem.imgPosition,
             };

+ 1 - 0
src/views/book/courseware/preview/components/dialogue_article/NormalModelChs.vue

@@ -1077,6 +1077,7 @@ export default {
               matchWords: wItem.matchWords,
               matchNotes: wItem.matchNotes,
               notesColor: wItem.notesColor,
+              matchNotesObj: wItem.matchNotesObj,
               img: wItem.img,
               imgPosition: wItem.imgPosition,
             };

+ 1 - 0
src/views/book/courseware/preview/components/dialogue_article/PhraseModelChs.vue

@@ -966,6 +966,7 @@ export default {
               matchWords: wItem.matchWords,
               matchNotes: wItem.matchNotes,
               notesColor: wItem.notesColor,
+              matchNotesObj: wItem.matchNotesObj,
               img: wItem.img,
               imgPosition: wItem.imgPosition,
             };

+ 1 - 0
src/views/book/courseware/preview/components/dialogue_article/Practicechs.vue

@@ -1094,6 +1094,7 @@ export default {
               matchWords: wItem.matchWords,
               matchNotes: wItem.matchNotes,
               notesColor: wItem.notesColor,
+              matchNotesObj: wItem.matchNotesObj,
               img: wItem.img,
               imgPosition: wItem.imgPosition,
             };

+ 1 - 0
src/views/book/courseware/preview/components/dialogue_article/WordModelChs.vue

@@ -827,6 +827,7 @@ export default {
               matchWords: wItem.matchWords,
               matchNotes: wItem.matchNotes,
               notesColor: wItem.notesColor,
+              matchNotesObj: wItem.matchNotesObj,
               img: wItem.img,
               imgPosition: wItem.imgPosition,
             };

+ 19 - 3
src/views/book/courseware/preview/components/dialogue_article/index.vue

@@ -208,18 +208,33 @@
         </div>
       </div>
       <template
-        v-if="data.new_word_list && data.new_word_list.new_word_list && data.new_word_list.new_word_list.length > 0"
+        v-if="
+          data.new_word_list &&
+          data.new_word_list.new_word_list &&
+          data.new_word_list.new_word_list.length > 0 &&
+          data.new_word_list.property.is_show === 'true'
+        "
       >
         <NewWordPreview :new-data="data.new_word_list" :is-mobile="isMobile" />
       </template>
       <template
         v-if="
-          data.other_word_list && data.other_word_list.new_word_list && data.other_word_list.new_word_list.length > 0
+          data.other_word_list &&
+          data.other_word_list.new_word_list &&
+          data.other_word_list.new_word_list.length > 0 &&
+          data.other_word_list.property.is_show === 'true'
         "
       >
         <NewWordPreview :new-data="data.other_word_list" :is-mobile="isMobile" />
       </template>
-      <template v-if="data.notes_list && data.notes_list.option && data.notes_list.option.length > 0">
+      <template
+        v-if="
+          data.notes_list &&
+          data.notes_list.option &&
+          data.notes_list.option.length > 0 &&
+          data.notes_list.property.is_show === 'true'
+        "
+      >
         <NotesPreview :notes-data="data.notes_list" :is-mobile="isMobile" />
       </template>
     </div>
@@ -592,6 +607,7 @@ export default {
               matchWords: wItem.matchWords,
               matchNotes: wItem.matchNotes,
               notesColor: wItem.notesColor,
+              matchNotesObj: wItem.matchNotesObj,
               img: wItem.img,
               imgPosition: wItem.imgPosition,
             };

+ 1 - 1
src/views/book/courseware/preview/components/notes/NotesPreview.vue

@@ -149,7 +149,7 @@
                 }"
                 v-html="convertText(sanitizeHTML(item.note))"
               ></div>
-              <div v-if="item.file_list[0]" class="NPC-notes-note-img">
+              <div v-if="item.file_list && item.file_list[0]" class="NPC-notes-note-img">
                 <el-image
                   :src="item.file_list[0].file_url"
                   :preview-src-list="[item.file_list[0].file_url]"