浏览代码

拼音显示优化

dsy 1 月之前
父节点
当前提交
62a66b637d
共有 23 个文件被更改,包括 425 次插入97 次删除
  1. 33 10
      src/components/PinyinText.vue
  2. 2 0
      src/views/book/courseware/create/components/base/common/CorrectPinyin.vue
  3. 19 26
      src/views/book/courseware/create/components/base/rich_text/RichText.vue
  4. 5 4
      src/views/book/courseware/create/components/base/stem/Stem.vue
  5. 91 1
      src/views/book/courseware/create/components/common/ModuleMixin.js
  6. 3 1
      src/views/book/courseware/create/components/common/SettingMixin.js
  7. 24 0
      src/views/book/courseware/create/components/question/fill/FillSetting.vue
  8. 30 3
      src/views/book/courseware/create/components/question/judge/Judge.vue
  9. 24 0
      src/views/book/courseware/create/components/question/judge/JudgeSetting.vue
  10. 42 0
      src/views/book/courseware/create/components/question/matching/Matching.vue
  11. 24 0
      src/views/book/courseware/create/components/question/matching/MatchingSetting.vue
  12. 1 32
      src/views/book/courseware/create/components/question/select/Select.vue
  13. 0 3
      src/views/book/courseware/create/components/question/select/SelectSetting.vue
  14. 27 0
      src/views/book/courseware/create/components/question/sort/Sort.vue
  15. 24 0
      src/views/book/courseware/create/components/question/sort/SortSetting.vue
  16. 12 11
      src/views/book/courseware/create/components/question/table/Table.vue
  17. 4 0
      src/views/book/courseware/data/fill.js
  18. 9 0
      src/views/book/courseware/data/judge.js
  19. 15 1
      src/views/book/courseware/data/matching.js
  20. 10 0
      src/views/book/courseware/data/sort.js
  21. 9 2
      src/views/book/courseware/preview/components/judge/JudgePreview.vue
  22. 9 2
      src/views/book/courseware/preview/components/matching/MatchingPreview.vue
  23. 8 1
      src/views/book/courseware/preview/components/sort/SortPreview.vue

+ 33 - 10
src/components/PinyinText.vue

@@ -8,18 +8,24 @@
         :style="{ 'align-items': pinyinPosition === 'top' ? 'flex-end' : 'flex-start' }"
       >
         <div v-for="(item, k) in sentence" :key="k" class="pinyin-text">
-          <span v-if="pinyinPosition === 'top'" class="pinyin" :class="{ active: visible && word_index == k }">
-            {{ item.pinyin.replace(/\s+/g, '') }}
-          </span>
           <span
             :class="{ active: visible && word_index == k }"
             :title="isPreview ? '' : '点击校对'"
-            :style="{ ...item.activeTextStyle, cursor: isPreview ? '' : 'pointer' }"
+            :style="{
+              ...item.activeTextStyle,
+              cursor: isPreview ? '' : 'pointer',
+            }"
             @click="correctPinyin(item, i, j, k)"
           >
-            {{ item.text }}
+            <ruby
+              v-for="(word, w) in item.text.split('')"
+              :key="w"
+              :style="{ 'ruby-position': pinyinPosition === 'top' ? 'over' : 'under' }"
+              class="py-char"
+              >{{ word
+              }}<rt class="pinyin" :class="{ active: visible && word_index == k }">{{ item.pinyin.split(' ')[w] }}</rt>
+            </ruby>
           </span>
-          <span v-if="pinyinPosition === 'bottom'" class="pinyin">{{ item.pinyin.replace(/\s+/g, '') }}</span>
         </div>
       </div>
     </div>
@@ -27,8 +33,10 @@
     <CorrectPinyin :visible.sync="visible" :select-content="selectContent" @fillTonePinyin="fillTonePinyin" />
   </div>
 </template>
+
 <script>
 import CorrectPinyin from '@/views/book/courseware/create/components/base/common/CorrectPinyin.vue';
+
 export default {
   name: 'PinyinText',
   components: {
@@ -72,7 +80,12 @@ export default {
     },
     // 回填校对后的拼音
     fillTonePinyin(dataContent) {
-      this.$emit('fillCorrectPinyin', dataContent, this.paragraph_index, this.sentence_index, this.word_index);
+      this.$emit('fillCorrectPinyin', {
+        selectContent: dataContent,
+        i: this.paragraph_index,
+        j: this.sentence_index,
+        k: this.word_index,
+      });
     },
   },
 };
@@ -90,20 +103,30 @@ export default {
       column-gap: 4px;
 
       .pinyin-text {
-        display: flex;
-        flex-direction: column;
         font-size: 24px;
 
+        .py-char {
+          ruby-align: center;
+        }
+
         .pinyin {
+          margin-bottom: 4px;
           font-family: 'League';
           font-size: 12px;
+          color: $font-color;
         }
       }
     }
   }
 
   .active {
-    color: rgb(242, 85, 90);
+    color: rgb(242, 85, 90) !important;
   }
 }
 </style>
+
+<style lang="scss">
+.pinyin-area + .pinyin-area {
+  margin-top: 4px;
+}
+</style>

+ 2 - 0
src/views/book/courseware/create/components/base/common/CorrectPinyin.vue

@@ -45,6 +45,8 @@
 
 <script>
 import { addTone, handleToneValue } from '@/utils/common';
+import _ from 'lodash';
+
 export default {
   name: 'CorrectPinyin',
   props: {

+ 19 - 26
src/views/book/courseware/create/components/base/rich_text/RichText.vue

@@ -15,7 +15,6 @@
           @compareAnnotationAndSave="compareAnnotationAndSave"
         />
         <el-button class="btn" @click="openMultilingual">多语言</el-button>
-        <el-divider v-if="isEnable(data.property.view_pinyin)" content-position="left">拼音效果</el-divider>
         <MultilingualFill
           :visible.sync="multilingualVisible"
           :text="data.content"
@@ -99,31 +98,26 @@ export default {
     },
     // 获取拼音解析文本
     crateParsedTextInfoPinyin(text) {
+      const data = this.data.paragraph_list_parameter;
       if (text === '') {
-        this.data.paragraph_list_parameter.pinyin_proofread_word_list = [];
+        data.pinyin_proofread_word_list = [];
         return;
       }
-      this.data.paragraph_list_parameter.text = text.replace(/<[^>]+>/g, '');
-      this.data.paragraph_list_parameter.is_first_sentence_first_hz_pinyin_first_char_upper_case =
+      data.text = text.replace(/<[^>]+>/g, '');
+      data.is_first_sentence_first_hz_pinyin_first_char_upper_case =
         this.data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case;
-      CrateParsedTextInfo_Pinyin(this.data.paragraph_list_parameter).then((res) => {
-        if (res.parsed_text) {
-          const mergedData = res.parsed_text.paragraph_list.map((outerArr, i) =>
+      CrateParsedTextInfo_Pinyin(data).then(({ parsed_text }) => {
+        if (parsed_text) {
+          // 合并 activeTextStyle
+          const mergedData = parsed_text.paragraph_list.map((outerArr, i) =>
             outerArr.map((innerArr, j) =>
-              innerArr.map((newItem, k) => {
-                // 从 originalData 中找到对应的项
-                const originalItem = this.data.paragraph_list[i]?.[j]?.[k];
-
+              innerArr.map((newItem, k) => ({
+                ...newItem,
                 // 如果 originalItem 有 activeTextStyle,就合并到 newItem
-                if (originalItem?.activeTextStyle) {
-                  return {
-                    ...newItem,
-                    activeTextStyle: originalItem.activeTextStyle,
-                  };
-                }
-                // 否则直接返回 newItem
-                return newItem;
-              }),
+                ...(this.data.paragraph_list[i]?.[j]?.[k]?.activeTextStyle && {
+                  activeTextStyle: this.data.paragraph_list[i][j][k].activeTextStyle,
+                }),
+              })),
             ),
           );
           this.data.paragraph_list = mergedData; // 取出合并后的数组
@@ -131,17 +125,16 @@ export default {
       });
     },
     // 填充校对后的拼音
-    fillCorrectPinyin(selectContent, i, j, k) {
-      // console.info('保存之后:', selectContent);
+    fillCorrectPinyin({ selectContent: { text, pinyin, activeTextStyle }, i, j, k }) {
       this.data.paragraph_list_parameter.pinyin_proofread_word_list.push({
         paragraph_index: i,
         sentence_index: j,
         word_index: k,
-        word: selectContent.text,
-        pinyin: selectContent.pinyin,
+        word: text,
+        pinyin,
       });
-      if (selectContent.pinyin) this.data.paragraph_list[i][j][k].pinyin = selectContent.pinyin;
-      this.data.paragraph_list[i][j][k].activeTextStyle = selectContent.activeTextStyle;
+      if (pinyin) this.data.paragraph_list[i][j][k].pinyin = pinyin;
+      if (activeTextStyle) this.data.paragraph_list[i][j][k].activeTextStyle = activeTextStyle;
     },
     // 思维导图
     handlerMindMap() {

+ 5 - 4
src/views/book/courseware/create/components/base/stem/Stem.vue

@@ -84,15 +84,16 @@ export default {
       });
     },
     // 填充校对后的拼音
-    fillCorrectPinyin({ selectContent, tonePinyin, i, j, k }) {
+    fillCorrectPinyin({ selectContent: { text, pinyin, activeTextStyle }, i, j, k }) {
       this.data.paragraph_list_parameter.pinyin_proofread_word_list.push({
         paragraph_index: i,
         sentence_index: j,
         word_index: k,
-        word: selectContent,
-        pinyin: tonePinyin,
+        word: text,
+        pinyin,
       });
-      this.data.paragraph_list[i][j][k].pinyin = tonePinyin;
+      if (pinyin) this.data.paragraph_list[i][j][k].pinyin = pinyin;
+      if (activeTextStyle) this.data.paragraph_list[i][j][k].activeTextStyle = activeTextStyle;
     },
     // 思维导图
     handlerMindMap() {

+ 91 - 1
src/views/book/courseware/create/components/common/ModuleMixin.js

@@ -5,7 +5,11 @@ import RichText from '@/components/RichText.vue';
 import MultilingualFill from '@/views/book/components/MultilingualFill.vue';
 
 import { displayList, viewMethodList, isEnable } from '@/views/book/courseware/data/common';
-import { ContentSaveCoursewareComponentContent, ContentGetCoursewareComponentContent } from '@/api/book';
+import {
+  ContentSaveCoursewareComponentContent,
+  ContentGetCoursewareComponentContent,
+  CrateParsedTextInfo_Pinyin,
+} from '@/api/book';
 
 const mixin = {
   data() {
@@ -137,6 +141,92 @@ const mixin = {
     handleMultilingualTranslation(multilingual) {
       this.data.multilingual = multilingual;
     },
+    /**
+     * 获取并设置拼音解析文本
+     * @param {String} text
+     * @param {Number} i
+     * @param {Number} j
+     */
+    crateParsedTextInfoPinyin(text, i = -1, j = -1) {
+      let data = null;
+      if (i === -1) {
+        data = this.data;
+      } else if (i >= 0 && j === -1) {
+        data = this.data.option_list[i];
+      } else if (i >= 0 && j >= 0) {
+        data = this.data.option_list[i][j];
+      }
+      if (text === '') {
+        data.pinyin_proofread_word_list = [];
+        return;
+      }
+
+      data.paragraph_list_parameter.text = text;
+
+      CrateParsedTextInfo_Pinyin({
+        ...data.paragraph_list_parameter,
+        is_first_sentence_first_hz_pinyin_first_char_upper_case:
+          this.data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case,
+      }).then(({ parsed_text }) => {
+        if (parsed_text) {
+          // 合并 activeTextStyle
+          const mergedData = parsed_text.paragraph_list.map((outerArr, i) =>
+            outerArr.map((innerArr, j) =>
+              innerArr.map((newItem, k) => ({
+                ...newItem,
+                // 如果 originalItem 有 activeTextStyle,就合并到 newItem
+                ...(data.paragraph_list?.[i]?.[j]?.[k]?.activeTextStyle && {
+                  activeTextStyle: data.paragraph_list[i][j][k].activeTextStyle,
+                }),
+              })),
+            ),
+          );
+          data.paragraph_list = mergedData;
+        }
+      });
+    },
+    /**
+     * 填充校对后的拼音
+     * @param {Object} param0 拼音参数
+     * @param {Number} col 列索引
+     * @param {Number} row 行索引
+     */
+    fillCorrectPinyin({ selectContent: { text, pinyin, activeTextStyle }, i, j, k }, row = -1, col = -1) {
+      let data = null;
+      if (row === -1) {
+        data = this.data.paragraph_list_parameter;
+      } else if (row >= 0 && col === -1) {
+        data = this.data.option_list[row].paragraph_list_parameter;
+      } else if (row >= 0 && col >= 0) {
+        data = this.data.option_list[row][col].paragraph_list_parameter;
+      }
+
+      if (!Array.isArray(data.pinyin_proofread_word_list)) {
+        data.pinyin_proofread_word_list = [];
+      }
+
+      data.pinyin_proofread_word_list.push({
+        paragraph_index: i,
+        sentence_index: j,
+        word_index: k,
+        word: text,
+        pinyin,
+      });
+
+      let listItem = null;
+      if (row === -1) {
+        listItem = this.data.paragraph_list?.[i]?.[j]?.[k];
+      } else if (row >= 0 && col === -1) {
+        listItem = this.data.option_list?.[row]?.paragraph_list?.[i]?.[j]?.[k];
+      } else if (row >= 0 && col >= 0) {
+        listItem = this.data.option_list?.[row]?.[col]?.paragraph_list?.[i]?.[j]?.[k];
+      }
+
+      if (listItem) {
+        if (pinyin) listItem.pinyin = pinyin;
+        if (activeTextStyle) listItem.activeTextStyle = activeTextStyle;
+      }
+    },
   },
 };
 

+ 3 - 1
src/views/book/courseware/create/components/common/SettingMixin.js

@@ -1,4 +1,4 @@
-import { checkString } from '@/views/book/courseware/data/common';
+import { checkString, isEnable, pinyinPositionList } from '@/views/book/courseware/data/common';
 
 import SerailNumber from '@/views/book/courseware/create/components/common/SerialNumber.vue';
 
@@ -7,6 +7,8 @@ const mixin = {
     return {
       param: {}, // 组件设置时传过来的特有参数
       checkString,
+      isEnable,
+      pinyinPositionList,
     };
   },
   components: {

+ 24 - 0
src/views/book/courseware/create/components/question/fill/FillSetting.vue

@@ -43,6 +43,30 @@
           </el-radio>
         </el-radio-group>
       </el-form-item>
+
+      <el-form-item label="拼音">
+        <el-switch v-model="property.view_pinyin" active-value="true" inactive-value="false" />
+      </el-form-item>
+      <el-form-item v-show="isEnable(property.view_pinyin)" label="拼音位置">
+        <el-radio
+          v-for="{ value, label } in pinyinPositionList"
+          :key="value"
+          v-model="property.pinyin_position"
+          :label="value"
+          :disabled="!isEnable(property.view_pinyin)"
+        >
+          {{ label }}
+        </el-radio>
+      </el-form-item>
+      <el-form-item v-show="isEnable(property.view_pinyin)" label="">
+        <el-checkbox
+          v-model="property.is_first_sentence_first_hz_pinyin_first_char_upper_case"
+          :disabled="!isEnable(property.view_pinyin)"
+          true-label="true"
+          false-label="false"
+          >句首大写</el-checkbox
+        >
+      </el-form-item>
     </el-form>
   </div>
 </template>

+ 30 - 3
src/views/book/courseware/create/components/question/judge/Judge.vue

@@ -23,7 +23,7 @@
             <SvgIcon v-if="option_type === option_type_list[1].value" icon-class="cross" size="8" />
             <SvgIcon v-if="option_type === option_type_list[2].value" icon-class="circle" size="10" />
           </div>
-          <span v-if="i > 0" class="delete" @click="deleteOption">
+          <span v-if="data.option_list.length > 2" class="delete" @click="deleteOption(i)">
             <SvgIcon icon-class="delete-2" width="12" height="12" />
           </span>
         </li>
@@ -32,17 +32,32 @@
         <SvgIcon icon-class="add-circle" width="14" height="14" />
         <span class="add-button" @click="addOption">增加选项</span>
       </div>
+
+      <el-divider v-if="isEnable(data.property.view_pinyin)" content-position="left">拼音效果</el-divider>
+      <PinyinText
+        v-for="(item, i) in data.option_list"
+        v-show="isEnable(data.property.view_pinyin)"
+        :key="i"
+        ref="PinyinText"
+        :paragraph-list="item.paragraph_list"
+        :pinyin-position="data.property.pinyin_position"
+        @fillCorrectPinyin="fillCorrectPinyin($event, i)"
+      />
     </template>
   </ModuleBase>
 </template>
 
 <script>
-import ModuleMixin from '../../common/ModuleMixin';
 import { getJudgeData, getOption, option_type_list, isEnable } from '@/views/book/courseware/data/judge';
 
+import ModuleMixin from '../../common/ModuleMixin';
+import PinyinText from '@/components/PinyinText.vue';
+
 export default {
   name: 'JudgePage',
-  components: {},
+  components: {
+    PinyinText,
+  },
   mixins: [ModuleMixin],
   data() {
     return {
@@ -63,6 +78,18 @@ export default {
   },
   watch: {
     'data.option_list': 'handleMindMap',
+    'data.property': {
+      handler({ view_pinyin }) {
+        if (!isEnable(view_pinyin)) return;
+        this.data.option_list.forEach((item, i) => {
+          const text = item.content.replace(/<[^>]+>/g, '');
+          if (!text) return;
+          item.paragraph_list_parameter.text = text;
+          this.crateParsedTextInfoPinyin(text, i);
+        });
+      },
+      deep: true,
+    },
   },
   methods: {
     // 将数字转换为小写字母

+ 24 - 0
src/views/book/courseware/create/components/question/judge/JudgeSetting.vue

@@ -9,6 +9,30 @@
           </el-radio>
         </el-radio-group>
       </el-form-item>
+
+      <el-form-item label="拼音">
+        <el-switch v-model="property.view_pinyin" active-value="true" inactive-value="false" />
+      </el-form-item>
+      <el-form-item v-show="isEnable(property.view_pinyin)" label="拼音位置">
+        <el-radio
+          v-for="{ value, label } in pinyinPositionList"
+          :key="value"
+          v-model="property.pinyin_position"
+          :label="value"
+          :disabled="!isEnable(property.view_pinyin)"
+        >
+          {{ label }}
+        </el-radio>
+      </el-form-item>
+      <el-form-item v-show="isEnable(property.view_pinyin)" label="">
+        <el-checkbox
+          v-model="property.is_first_sentence_first_hz_pinyin_first_char_upper_case"
+          :disabled="!isEnable(property.view_pinyin)"
+          true-label="true"
+          false-label="false"
+          >句首大写</el-checkbox
+        >
+      </el-form-item>
     </el-form>
   </div>
 </template>

+ 42 - 0
src/views/book/courseware/create/components/question/matching/Matching.vue

@@ -33,6 +33,20 @@
         </li>
       </ul>
 
+      <el-divider v-if="isEnable(data.property.view_pinyin)" content-position="left">拼音效果</el-divider>
+      <template v-if="isEnable(data.property.view_pinyin)">
+        <div v-for="(item, i) in data.option_list" :key="i" class="pinyin-text-list">
+          <PinyinText
+            v-for="(li, j) in item"
+            :key="`${i}-${j}`"
+            ref="PinyinText"
+            :paragraph-list="li.paragraph_list"
+            :pinyin-position="data.property.pinyin_position"
+            @fillCorrectPinyin="fillCorrectPinyin($event, i, j)"
+          />
+        </div>
+      </template>
+
       <MultilingualFill
         v-if="curSelectRow !== -1 && curSelectColumn !== -1"
         :visible.sync="multilingualVisible"
@@ -46,12 +60,16 @@
 
 <script>
 import ModuleMixin from '../../common/ModuleMixin';
+import PinyinText from '@/components/PinyinText.vue';
 
 import { getMatchingData, getOption, getOptionItem } from '@/views/book/courseware/data/matching';
 import { computeOptionMethods, serialNumberTypeList } from '@/views/book/courseware/data/common';
 
 export default {
   name: 'MatchingPage',
+  components: {
+    PinyinText,
+  },
   mixins: [ModuleMixin],
   data() {
     return {
@@ -136,6 +154,20 @@ export default {
       },
       'handlerMindMap',
     ],
+    'data.property': {
+      handler({ view_pinyin }) {
+        if (!this.isEnable(view_pinyin)) return;
+        this.data.option_list.forEach((item, i) => {
+          item.forEach((option, j) => {
+            const text = option.content.replace(/<[^>]+>/g, '');
+            if (!text) return;
+            option.paragraph_list_parameter.text = text;
+            this.crateParsedTextInfoPinyin(text, i, j);
+          });
+        });
+      },
+      deep: true,
+    },
   },
   methods: {
     /**
@@ -224,4 +256,14 @@ export default {
     }
   }
 }
+
+.pinyin-text-list {
+  display: flex;
+  column-gap: 24px;
+  align-items: center;
+
+  + .pinyin-text-list {
+    margin-top: 4px;
+  }
+}
 </style>

+ 24 - 0
src/views/book/courseware/create/components/question/matching/MatchingSetting.vue

@@ -23,6 +23,30 @@
       <el-form-item label="行数">
         <el-input-number v-model="property.row_num" :min="1" />
       </el-form-item>
+
+      <el-form-item label="拼音">
+        <el-switch v-model="property.view_pinyin" active-value="true" inactive-value="false" />
+      </el-form-item>
+      <el-form-item v-show="isEnable(property.view_pinyin)" label="拼音位置">
+        <el-radio
+          v-for="{ value, label } in pinyinPositionList"
+          :key="value"
+          v-model="property.pinyin_position"
+          :label="value"
+          :disabled="!isEnable(property.view_pinyin)"
+        >
+          {{ label }}
+        </el-radio>
+      </el-form-item>
+      <el-form-item v-show="isEnable(property.view_pinyin)" label="">
+        <el-checkbox
+          v-model="property.is_first_sentence_first_hz_pinyin_first_char_upper_case"
+          :disabled="!isEnable(property.view_pinyin)"
+          true-label="true"
+          false-label="false"
+          >句首大写</el-checkbox
+        >
+      </el-form-item>
     </el-form>
   </div>
 </template>

+ 1 - 32
src/views/book/courseware/create/components/question/select/Select.vue

@@ -50,8 +50,6 @@ import ModuleMixin from '../../common/ModuleMixin';
 import PinyinText from '@/components/PinyinText.vue';
 
 import { getSelectData, getOption, arrangeTypeList } from '@/views/book/courseware/data/select';
-import { isEnable } from '@/views/book/courseware/data/common';
-import { CrateParsedTextInfo_Pinyin } from '@/api/book';
 
 export default {
   name: 'SelectPage',
@@ -70,7 +68,7 @@ export default {
     'data.answer.answer_list': 'handlerMindMap',
     'data.property': {
       handler({ view_pinyin }) {
-        if (!isEnable(view_pinyin)) return;
+        if (!this.isEnable(view_pinyin)) return;
         this.data.option_list.forEach((item, i) => {
           const text = item.content.replace(/<[^>]+>/g, '');
           if (!text) return;
@@ -130,35 +128,6 @@ export default {
     handleMultilingualTranslation(translations) {
       this.$set(this.data.option_list[this.curSelectIndex], 'multilingual', translations);
     },
-    // 获取拼音解析文本
-    crateParsedTextInfoPinyin(text, i) {
-      const data = this.data.option_list[i];
-      if (text === '') {
-        data.paragraph_list_parameter.pinyin_proofread_word_list = [];
-        return;
-      }
-      data.paragraph_list_parameter.text = text;
-      CrateParsedTextInfo_Pinyin({
-        ...data.paragraph_list_parameter,
-        is_first_sentence_first_hz_pinyin_first_char_upper_case:
-          this.data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case,
-      }).then(({ parsed_text }) => {
-        if (parsed_text) {
-          data.paragraph_list = parsed_text.paragraph_list;
-        }
-      });
-    },
-    // 填充校对后的拼音
-    fillCorrectPinyin({ selectContent, tonePinyin, i, j, k }, index) {
-      this.data.option_list[index].paragraph_list_parameter.pinyin_proofread_word_list.push({
-        paragraph_index: i,
-        sentence_index: j,
-        word_index: k,
-        word: selectContent,
-        pinyin: tonePinyin,
-      });
-      this.data.option_list[index].paragraph_list[i][j][k].pinyin = tonePinyin;
-    },
   },
 };
 </script>

+ 0 - 3
src/views/book/courseware/create/components/question/select/SelectSetting.vue

@@ -45,7 +45,6 @@
 import SettingMixin from '@/views/book/courseware/create/components/common/SettingMixin';
 
 import { arrangeTypeList, getSelectProperty } from '@/views/book/courseware/data/select';
-import { isEnable, pinyinPositionList } from '@/views/book/courseware/data/common';
 
 export default {
   name: 'SelectSetting',
@@ -54,8 +53,6 @@ export default {
     return {
       arrangeTypeList,
       property: getSelectProperty(),
-      isEnable,
-      pinyinPositionList,
     };
   },
   methods: {},

+ 27 - 0
src/views/book/courseware/create/components/question/sort/Sort.vue

@@ -35,6 +35,17 @@
       </div>
       <div class="tips">{{ tips }}</div>
 
+      <el-divider v-if="isEnable(data.property.view_pinyin)" content-position="left">拼音效果</el-divider>
+      <PinyinText
+        v-for="(item, i) in data.option_list"
+        v-show="isEnable(data.property.view_pinyin)"
+        :key="i"
+        ref="PinyinText"
+        :paragraph-list="item.paragraph_list"
+        :pinyin-position="data.property.pinyin_position"
+        @fillCorrectPinyin="fillCorrectPinyin($event, i)"
+      />
+
       <MultilingualFill
         v-if="curSelectIndex !== -1"
         :visible.sync="multilingualVisible"
@@ -48,11 +59,15 @@
 
 <script>
 import ModuleMixin from '../../common/ModuleMixin';
+import PinyinText from '@/components/PinyinText.vue';
 
 import { arrangeTypeList, getSortData, getOption, orderTypeList } from '@/views/book/courseware/data/sort';
 
 export default {
   name: 'SortPage',
+  components: {
+    PinyinText,
+  },
   mixins: [ModuleMixin],
   data() {
     return {
@@ -87,6 +102,18 @@ export default {
     ],
     'data.property.arrange_direction': 'handleMindMap',
     'data.property.order_type': 'handleMindMap',
+    'data.property': {
+      handler({ view_pinyin }) {
+        if (!this.isEnable(view_pinyin)) return;
+        this.data.option_list.forEach((item, i) => {
+          const text = item.content.replace(/<[^>]+>/g, '');
+          if (!text) return;
+          item.paragraph_list_parameter.text = text;
+          this.crateParsedTextInfoPinyin(text, i);
+        });
+      },
+      deep: true,
+    },
   },
   methods: {
     getSortWrapperStyle() {

+ 24 - 0
src/views/book/courseware/create/components/question/sort/SortSetting.vue

@@ -23,6 +23,30 @@
           </el-radio>
         </el-radio-group>
       </el-form-item>
+
+      <el-form-item label="拼音">
+        <el-switch v-model="property.view_pinyin" active-value="true" inactive-value="false" />
+      </el-form-item>
+      <el-form-item v-show="isEnable(property.view_pinyin)" label="拼音位置">
+        <el-radio
+          v-for="{ value, label } in pinyinPositionList"
+          :key="value"
+          v-model="property.pinyin_position"
+          :label="value"
+          :disabled="!isEnable(property.view_pinyin)"
+        >
+          {{ label }}
+        </el-radio>
+      </el-form-item>
+      <el-form-item v-show="isEnable(property.view_pinyin)" label="">
+        <el-checkbox
+          v-model="property.is_first_sentence_first_hz_pinyin_first_char_upper_case"
+          :disabled="!isEnable(property.view_pinyin)"
+          true-label="true"
+          false-label="false"
+          >句首大写</el-checkbox
+        >
+      </el-form-item>
     </el-form>
   </div>
 </template>

+ 12 - 11
src/views/book/courseware/create/components/question/table/Table.vue

@@ -65,14 +65,14 @@
           <div v-for="li in item" :key="li.mark" class="table-item">
             <!-- eslint-disable max-len -->
             <RichText
+              v-if="data.mode === 'normal'"
               ref="richText"
               v-model="li.content"
               :inline="true"
               toolbar="fontselect fontsizeselect forecolor backcolor | underline | bold italic strikethrough alignleft aligncenter alignright"
-              v-if="data.mode === 'normal'"
               @handleRichTextBlur="handleBlurCon"
             />
-            <el-input v-else v-model="li.content" @blur="handleBlurCon"></el-input>
+            <el-input v-else v-model="li.content" @blur="handleBlurCon" />
           </div>
         </div>
         <div class="table-node">
@@ -89,7 +89,7 @@
         <div class="option-list">
           <div v-for="(item, i) in data.answer_list" :key="i" class="table-node">
             <div v-for="(li, j) in item" :key="i + 'col' + j" class="table-item">
-              <el-input v-model="li.answer" type="textarea"></el-input>
+              <el-input v-model="li.answer" type="textarea" />
             </div>
           </div>
         </div>
@@ -130,7 +130,7 @@ import {
 } from '@/views/book/courseware/data/table';
 
 export default {
-  name: 'Table',
+  name: 'TablePage',
   components: {
     PinyinText,
   },
@@ -193,7 +193,7 @@ export default {
         let text = '';
         this.data.option_list.forEach((item) => {
           item.forEach((items) => {
-            text += items.content.replace(/<[^>]+>/g, '') + '\n';
+            text += `${items.content.replace(/<[^>]+>/g, '')}\n`;
           });
         });
         if (isEnable(val) && text) {
@@ -241,7 +241,7 @@ export default {
                 // .replace(/<span class="rich-fill".*?>(.*?)<\/span>|([_]{3,})/gi, '###$1$2###');
               });
           }
-          text += items.content.replace(/<[^>]+>/g, '') + '\n';
+          text += `${items.content.replace(/<[^>]+>/g, '')}\n`;
         });
       });
       if (isEnable(this.data.property.view_pinyin)) {
@@ -300,15 +300,16 @@ export default {
       });
     },
     // 填充校对后的拼音
-    fillCorrectPinyin(selectContent, tonePinyin, i, j, k) {
+    fillCorrectPinyin({ selectContent: { text, pinyin, activeTextStyle }, i, j, k }) {
       this.data.paragraph_list_parameter.pinyin_proofread_word_list.push({
         paragraph_index: i,
         sentence_index: j,
         word_index: k,
-        word: selectContent,
-        pinyin: tonePinyin,
+        word: text,
+        pinyin,
       });
-      this.data.paragraph_list[i][j][k].pinyin = tonePinyin;
+      if (pinyin) this.data.paragraph_list[i][j][k].pinyin = pinyin;
+      if (activeTextStyle) this.data.paragraph_list[i][j][k].activeTextStyle = activeTextStyle;
     },
     // 思维导图数据
     handleMindMap() {
@@ -330,7 +331,7 @@ export default {
       this.multilingualText = '';
       this.data.option_list.forEach((item) => {
         item.forEach((items) => {
-          this.multilingualText += items.content ? '<p>' + items.content + '</p>' : '<p>&nbsp;</p>';
+          this.multilingualText += items.content ? `<p>${items.content}</p>` : '<p>&nbsp;</p>';
         });
       });
       this.multilingualVisible = true;

+ 4 - 0
src/views/book/courseware/data/fill.js

@@ -4,6 +4,7 @@ import {
   serialNumberPositionList,
   arrangeTypeList,
   switchOption,
+  pinyinPositionList,
 } from '@/views/book/courseware/data/common';
 
 export { arrangeTypeList, switchOption };
@@ -57,6 +58,9 @@ export function getFillProperty() {
     audio_generation_method: audioGenerationMethodList[0].value,
     fill_font: fillFontList[0].value,
     is_enable_voice_answer: switchOption[0].value,
+    view_pinyin: 'false', // 显示拼音
+    pinyin_position: pinyinPositionList[0].value,
+    is_first_sentence_first_hz_pinyin_first_char_upper_case: displayList[0].value, // 句首大写
   };
 }
 

+ 9 - 0
src/views/book/courseware/data/judge.js

@@ -4,6 +4,7 @@ import {
   serialNumberPositionList,
   switchOption,
   isEnable,
+  pinyinPositionList,
 } from '@/views/book/courseware/data/common';
 import { getRandomNumber } from '@/utils';
 
@@ -24,6 +25,9 @@ export function getJudgeProperty() {
     sn_display_mode: displayList[0].value,
     option_type_list: [option_type_list[0].value, option_type_list[1].value, option_type_list[2].value],
     is_view_incertitude: switchOption[1].value,
+    view_pinyin: 'false', // 显示拼音
+    pinyin_position: pinyinPositionList[0].value,
+    is_first_sentence_first_hz_pinyin_first_char_upper_case: displayList[0].value, // 句首大写
   };
 }
 
@@ -31,6 +35,11 @@ export function getOption() {
   return {
     content: '',
     mark: getRandomNumber(),
+    paragraph_list: [], // 段落列表
+    paragraph_list_parameter: {
+      text: '',
+      pinyin_proofread_word_list: [],
+    },
   };
 }
 

+ 15 - 1
src/views/book/courseware/data/matching.js

@@ -1,4 +1,9 @@
-import { serialNumberTypeList, displayList, serialNumberPositionList } from '@/views/book/courseware/data/common';
+import {
+  serialNumberTypeList,
+  displayList,
+  serialNumberPositionList,
+  pinyinPositionList,
+} from '@/views/book/courseware/data/common';
 import { getRandomNumber } from '@/utils';
 
 /**
@@ -18,6 +23,9 @@ export function getMatchingProperty(column_num = 2) {
     serial_number_type_list: serialNumberTypeList.slice(0, column_num).map((item) => item.value),
     row_num: 2, // 行数
     column_num, // 列数 2 ~ 3
+    view_pinyin: 'false', // 显示拼音
+    pinyin_position: pinyinPositionList[0].value,
+    is_first_sentence_first_hz_pinyin_first_char_upper_case: displayList[0].value, // 句首大写
   };
 }
 
@@ -26,6 +34,12 @@ export function getOptionItem() {
     content: '',
     mark: getRandomNumber(),
     multilingual: [], // 多语言
+    paragraph_list: [], // 段落列表
+    // 段落列表参数
+    paragraph_list_parameter: {
+      text: '',
+      pinyin_proofread_word_list: [],
+    },
   };
 }
 

+ 10 - 0
src/views/book/courseware/data/sort.js

@@ -3,6 +3,7 @@ import {
   serialNumberTypeList,
   serialNumberPositionList,
   displayList,
+  pinyinPositionList,
 } from '@/views/book/courseware/data/common';
 import { getRandomNumber } from '@/utils';
 export { arrangeTypeList };
@@ -13,6 +14,12 @@ export function getOption() {
     content: '',
     custom_serial_number: '', // 自定义序号
     multilingual: [], // 多语言
+    paragraph_list: [], // 段落列表
+    // 段落列表参数
+    paragraph_list_parameter: {
+      text: '',
+      pinyin_proofread_word_list: [],
+    },
   };
 }
 
@@ -30,6 +37,9 @@ export function getSortProperty() {
     option_count: 3,
     arrange_direction: arrangeTypeList[0].value,
     order_type: orderTypeList[0].value,
+    view_pinyin: 'false', // 显示拼音
+    pinyin_position: pinyinPositionList[0].value,
+    is_first_sentence_first_hz_pinyin_first_char_upper_case: displayList[0].value, // 句首大写
   };
 }
 

+ 9 - 2
src/views/book/courseware/preview/components/judge/JudgePreview.vue

@@ -4,14 +4,21 @@
     <div class="main">
       <ul class="option-list">
         <li
-          v-for="({ content, mark }, i) in data.option_list"
+          v-for="({ content, mark, paragraph_list }, i) in data.option_list"
           :key="mark"
           :style="{ cursor: disabled ? 'not-allowed' : 'pointer' }"
           :class="['option-item', { active: isAnswer(mark) }]"
         >
           <div :class="['option-content', computedIsJudgeRight(mark)]">
             <span class="serial-number">{{ convertNumberToLetter(i) }}.</span>
-            <div class="rich-text" v-html="sanitizeHTML(content)"></div>
+            <PinyinText
+              v-if="isEnable(data.property.view_pinyin)"
+              class="content"
+              :paragraph-list="paragraph_list"
+              :pinyin-position="data.property.pinyin_position"
+              :is-preview="true"
+            />
+            <div v-else class="rich-text" v-html="sanitizeHTML(content)"></div>
           </div>
           <div class="option-type">
             <div

+ 9 - 2
src/views/book/courseware/preview/components/matching/MatchingPreview.vue

@@ -7,7 +7,7 @@
       <ul ref="list" class="option-list">
         <li v-for="(item, i) in data.option_list" :key="i" class="list-item">
           <div
-            v-for="({ content, mark, multilingual }, j) in item"
+            v-for="({ content, mark, multilingual, paragraph_list }, j) in item"
             :key="mark"
             :class="['item-wrapper', `item-${mark}`, computedAnswerClass(mark)]"
             :style="{ cursor: disabled ? 'default' : 'pointer' }"
@@ -15,7 +15,14 @@
             @mouseup="mouseup($event, i, j, mark)"
             @click="handleClickConnection($event, i, j, mark)"
           >
-            <span class="content rich-text" v-html="sanitizeHTML(content)"></span>
+            <PinyinText
+              v-if="isEnable(data.property.view_pinyin)"
+              class="content"
+              :paragraph-list="paragraph_list"
+              :pinyin-position="data.property.pinyin_position"
+              :is-preview="true"
+            />
+            <span v-else class="content rich-text" v-html="sanitizeHTML(content)"></span>
             <div v-if="showLang" class="lang">
               {{ multilingual.find((item) => item.type === getLang())?.translation }}
             </div>

+ 8 - 1
src/views/book/courseware/preview/components/sort/SortPreview.vue

@@ -24,7 +24,14 @@
               :class="['drag-item', ...computedDragItemClass(i)]"
               @click="handleClickItem(i)"
             >
-              <span class="rich-text" v-html="sanitizeHTML(item.content)"></span>
+              <PinyinText
+                v-if="isEnable(data.property.view_pinyin)"
+                class="content"
+                :paragraph-list="item.paragraph_list"
+                :pinyin-position="data.property.pinyin_position"
+                :is-preview="true"
+              />
+              <span v-else class="rich-text" v-html="sanitizeHTML(item.content)"></span>
               <div v-if="showLang" class="lang">
                 {{ item.multilingual.find((item) => item.type === getLang())?.translation }}
               </div>