2 Commits 33a32fa697 ... d028fa0daa

Auteur SHA1 Bericht Datum
  natasha d028fa0daa Merge branch 'lhd' 2 dagen geleden
  zq 87688fe51d 富文本可以隐藏部分拼音 3 dagen geleden

+ 33 - 7
src/components/PinyinText.vue

@@ -17,13 +17,21 @@
             }"
             @click="correctPinyin(item, i, j, k)"
           >
-            <span v-if="pinyinPosition === 'top'" class="pinyin" :style="{ 'font-size': pinyinSize }">{{
-              item.pinyin.replace(/\s+/g, '')
-            }}</span>
+            <span
+              v-if="pinyinPosition === 'top' && hasPinyinInParagraph(i)"
+              class="pinyin"
+              :style="{ 'font-size': pinyinSize }"
+            >
+              {{ getPinyinText(item) }}</span
+            >
             <span class="py-char" :style="textStyle(item)">{{ convertText(item.text) }}</span>
-            <span v-if="pinyinPosition !== 'top'" class="pinyin" :style="{ 'font-size': pinyinSize }">{{
-              item.pinyin.replace(/\s+/g, '')
-            }}</span>
+            <span
+              v-if="pinyinPosition !== 'top' && hasPinyinInParagraph(i)"
+              class="pinyin"
+              :style="{ 'font-size': pinyinSize }"
+            >
+              {{ getPinyinText(item) }}</span
+            >
           </span>
         </span>
       </span>
@@ -54,6 +62,7 @@
 <script>
 import CorrectPinyin from '@/views/book/courseware/create/components/base/common/CorrectPinyin.vue';
 import { sanitizeHTML } from '@/utils/common';
+import { isEnable } from '@/views/book/courseware/data/common';
 
 export default {
   name: 'PinyinText',
@@ -101,8 +110,8 @@ export default {
   },
   data() {
     return {
+      isEnable,
       sanitizeHTML,
-      paragraph_list: [],
       visible: false,
       selectContent: {},
       paragraph_index: 0,
@@ -223,6 +232,21 @@ export default {
         k: this.word_index,
       });
     },
+    // 如段落有拼音,则返回true ,否则不显示拼音行
+    hasPinyinInParagraph(paragraphIndex) {
+      const paragraph = this.paragraphList[paragraphIndex];
+      return paragraph.some((sentence) => sentence.some((item) => this.checkShowPinyin(item.showPinyin)));
+    },
+    // 兼容历史数据,没有showPinyin字段的,则默认为true
+    checkShowPinyin(showPinyin) {
+      if (showPinyin === undefined || showPinyin === null) {
+        return true;
+      }
+      return this.isEnable(showPinyin);
+    },
+    getPinyinText(item) {
+      return this.checkShowPinyin(item.showPinyin) ? item.pinyin.replace(/\s+/g, '') : '';
+    },
   },
 };
 </script>
@@ -248,6 +272,8 @@ export default {
         }
 
         .pinyin {
+          display: inline-block;
+          min-height: 12px;
           font-family: 'PINYIN-B';
           font-size: 12px;
           font-weight: lighter;

+ 12 - 9
src/components/RichText.vue

@@ -594,6 +594,9 @@ export default {
     }
   },
   methods: {
+    getRichContent() {
+      return tinymce.get(this.id).getContent();
+    },
     displayToolbar(isTitle, isInit) {
       if (!this.editorIsInited) {
         this.editorBeforeInitConfig['isTitle'] = isTitle;
@@ -937,7 +940,7 @@ export default {
       let start = editor.selection.getStart();
       if (isNodeType(start, 'span')) {
         let textContent = start.textContent;
-        let content = editor.selection.getContent();
+        let content = this.getRichContent();
         let str = textContent.split(content);
         start.remove();
         editor.selection.setContent(str.join(content));
@@ -949,7 +952,7 @@ export default {
     setContent() {
       let editor = tinymce.get(this.id);
       let start = editor.selection.getStart();
-      let content = editor.selection.getContent();
+      let content = this.getRichContent();
       if (isNodeType(start, 'span')) {
         let textContent = start.textContent;
         let str = textContent.split(content);
@@ -984,13 +987,13 @@ export default {
     // },
     handleRichTextBlur() {
       this.$emit('handleRichTextBlur', this.itemIndex);
-      let content = tinymce.get(this.id).getContent();
+      let content = this.getRichContent();
 
       if (this.isViewPinyin) {
-        // this.createParsedTextInfoPinyin(content);
-        let styles = this.getFirstCharStyles();
-        let text = content.replace(/<[^>]+>/g, '');
-        this.$emit('createParsedTextInfoPinyin', text, styles);
+        //updated by 2026-3-24 失去焦点时,不再生成拼音,改成手动点击生成拼音
+        // let styles = this.getFirstCharStyles();
+        //  let text = content.replace(/<[^>]+>/g, '');
+        //  this.$emit('createParsedTextInfoPinyin', text, styles);
         return;
       }
 
@@ -1116,7 +1119,7 @@ export default {
       let noteId = '';
       let editor = tinymce.get(this.id);
       let start = editor.selection.getStart();
-      let content = editor.selection.getContent();
+      let content = this.getRichContent();
       if (isNodeType(start, 'span')) {
         noteId = start.getAttribute('data-annotation-id');
       } else {
@@ -1136,7 +1139,7 @@ export default {
       let start = editor.selection.getStart();
       if (isNodeType(start, 'span')) {
         let textContent = start.textContent;
-        let content = editor.selection.getContent();
+        let content = this.getRichContent();
         let str = textContent.split(content);
         start.remove();
         editor.selection.setContent(str.join(content));

+ 44 - 4
src/views/book/courseware/create/components/base/common/CorrectPinyin.vue

@@ -34,10 +34,30 @@
         <SvgIcon icon-class="strikethrough" title="删除线" size="20" @click="setActiveTextStyle('line-through')" />
       </span>
     </div>
-    <span class="tone-pinyin">{{ dataContent.pinyin }}</span>
+    <span class="tone-pinyin" v-show="isEnable(dataContent.showPinyin)">{{ dataContent.pinyin }}</span>
     <span class="content-text" :style="dataContent.activeTextStyle">{{ dataContent.text }}</span>
-    <el-input v-model="numberPinyin" autocomplete="off" placeholder="请输入正确的拼音" @blur="convertTonePinyin" />
-    <span class="tips">一到四声分别用数字1-4表示,轻声用0表示,拼音间用空格隔开。</span>
+
+    <div class="pinyin-row">
+      <el-switch
+        v-model="dataContent.showPinyin"
+        active-value="true"
+        inactive-value="false"
+        active-text="显示拼音"
+        inactive-text="隐藏拼音"
+      />
+      <el-input
+        v-show="isEnable(dataContent.showPinyin)"
+        v-model="numberPinyin"
+        autocomplete="off"
+        placeholder="请输入正确的拼音"
+        @blur="convertTonePinyin"
+        class="pinyin-input"
+      />
+    </div>
+    <span v-show="isEnable(dataContent.showPinyin)" class="tips"
+      >一到四声分别用数字1-4表示,轻声用0表示,拼音间用空格隔开。</span
+    >
+
     <RichText
       v-if="componentType === 'richtext'"
       v-model="dataContent.note"
@@ -59,6 +79,7 @@ import { addTone, handleToneValue } from '@/utils/common';
 import RichText from '@/components/RichText.vue';
 import _ from 'lodash';
 import { fontFamilyList } from '@/views/book/courseware/data/table.js';
+import { isEnable } from '@/views/book/courseware/data/common';
 
 export default {
   name: 'CorrectPinyin',
@@ -82,6 +103,7 @@ export default {
 
   data() {
     return {
+      isEnable,
       numberPinyin: '',
       fontFamilyOptions: fontFamilyList,
       fontSizeOptions: [
@@ -126,6 +148,11 @@ export default {
             this.$set(style, key, this.activeTextStyle[key]);
           }
         }
+        let _showPinyin = this.dataContent.showPinyin;
+        if (_showPinyin === undefined || _showPinyin === null) {
+          _showPinyin = 'true';
+        }
+        this.$set(this.dataContent, 'showPinyin', _showPinyin);
         this.$set(this.dataContent, 'activeTextStyle', style);
       },
       deep: true,
@@ -134,6 +161,7 @@ export default {
   methods: {
     // 将数字拼音转换为声调拼音
     convertTonePinyin() {
+      if (!this.numberPinyin) return;
       this.dataContent.pinyin = this.numberPinyin
         .trim()
         .split(/\s+/)
@@ -230,7 +258,7 @@ export default {
     }
 
     .content-text {
-      margin-top: -12px;
+      /* margin-top: -12px; */
       font-size: 16px;
     }
 
@@ -255,4 +283,16 @@ export default {
     }
   }
 }
+
+.pinyin-row {
+  display: flex;
+  column-gap: 16px;
+  align-items: center;
+  width: 100%;
+  margin-bottom: 8px; // 与下方 tips 的间距
+
+  .pinyin-input {
+    flex: 1;
+  }
+}
 </style>

+ 24 - 1
src/views/book/courseware/create/components/base/rich_text/RichText.vue

@@ -18,12 +18,14 @@
           @compareAnnotationAndSave="compareAnnotationAndSave"
         />
         <el-button class="btn" @click="openMultilingual">多语言</el-button>
+
         <MultilingualFill
           :visible.sync="multilingualVisible"
           :text="data.content"
           :translations="data.multilingual"
           @SubmitTranslation="handleMultilingualTranslation"
         />
+
         <el-button
           v-show="isEnable(data.property.view_pinyin)"
           style="margin-left: 10px"
@@ -31,6 +33,7 @@
           @click.native="showWordFlag = true"
           >分词校对</el-button
         >
+
         <el-dialog
           v-if="showWordFlag"
           :visible.sync="showWordFlag"
@@ -45,6 +48,14 @@
           <CheckWord :data="wordData" @saveWord="saveWord" />
         </el-dialog>
 
+        <el-button
+          v-show="isEnable(data.property.view_pinyin)"
+          style="margin-left: 10px"
+          class="btn"
+          @click.native="generatPinyin"
+          >生成拼音</el-button
+        >
+
         <el-divider v-if="isEnable(data.property.view_pinyin)" content-position="left">拼音效果</el-divider>
         <PinyinText
           v-if="isEnable(data.property.view_pinyin)"
@@ -175,6 +186,16 @@ export default {
         this.createParsedTextInfoPinyin(text);
       }
     },
+    //生成拼音
+    generatPinyin() {
+      if (!isEnable(this.data.property.view_pinyin)) {
+        return;
+      }
+      let styles = this.$refs.richText.getFirstCharStyles();
+      let content = this.$refs.richText.getRichContent();
+      let text = content.replace(/<[^>]+>/g, '');
+      this.createParsedTextInfoPinyin(text, styles);
+    },
     showSetting() {
       this.richId = this.$refs.richText.id;
       this.$emit('showSetting', this.data.property, this.data.type, this.id, {
@@ -269,17 +290,19 @@ export default {
       return hash.toString(36); // 转为base36缩短长度
     },
     // 填充校对后的拼音
-    fillCorrectPinyin({ selectContent: { text, pinyin, activeTextStyle, note }, i, j, k }) {
+    fillCorrectPinyin({ selectContent: { text, pinyin, activeTextStyle, note, showPinyin }, i, j, k }) {
       this.data.paragraph_list_parameter.pinyin_proofread_word_list.push({
         paragraph_index: i,
         sentence_index: j,
         word_index: k,
         word: text,
         pinyin,
+        showPinyin,
       });
       if (pinyin) this.data.paragraph_list[i][j][k].pinyin = pinyin;
       if (activeTextStyle) this.data.paragraph_list[i][j][k].activeTextStyle = activeTextStyle;
       if (note) this.data.paragraph_list[i][j][k].note = note;
+      this.data.paragraph_list[i][j][k].showPinyin = showPinyin;
     },
     // 思维导图
     handlerMindMap() {