瀏覽代碼

提交描述和题干组件(其中校对拼音和句首大写未实现)

zq 1 年之前
父節點
當前提交
c18535701c

+ 7 - 0
src/api/book.js

@@ -160,3 +160,10 @@ export function GetCoursewareComponentContent_View(data) {
 export function DeleteCourseware(data) {
   return http.post(`${process.env.VUE_APP_BookWebSI}?MethodName=book-courseware_manager-DeleteCourseware`, data);
 }
+
+/**
+ * 为文本生成拼音解析文本
+ */
+export function CrateParsedTextInfo_Pinyin(data) {
+  return http.post(`/TeachingServer/TextAnalyser/CrateParsedTextInfo_Pinyin`, data);
+}

+ 62 - 0
src/components/PinyinText.vue

@@ -0,0 +1,62 @@
+<template>
+  <div class="pinyin-area">
+    <div v-for="(paragraph, i) in paragraphList" :key="i" class="pinyin-paragraph">
+      <div
+        v-for="(sentence, j) in paragraph"
+        :key="j"
+        class="pinyin-sentence"
+        :style="{ 'align-items': pinyinPosition === 'top' ? 'flex-end' : 'flex-start' }"
+      >
+        <div v-for="(text, k) in sentence" :key="k" class="pinyin-text">
+          <span v-if="pinyinPosition === 'top'" class="pinyin">{{ text.pinyin.replace(/\s+/g, '') }}</span>
+          <span class="text">{{ text.text }}</span>
+          <span v-if="pinyinPosition === 'bottom'" class="pinyin">{{ text.pinyin.replace(/\s+/g, '') }}</span>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  name: 'PinyinText',
+  props: {
+    paragraphList: {
+      type: Array,
+      required: true,
+    },
+    pinyinPosition: {
+      type: String,
+      required: true,
+    },
+  },
+  data() {
+    return {};
+  },
+  methods: {},
+};
+</script>
+
+<style lang="scss" scoped>
+.pinyin-area {
+  .pinyin-paragraph {
+    display: flex;
+    flex-direction: column;
+
+    .pinyin-sentence {
+      display: flex;
+      flex-wrap: wrap;
+      column-gap: 4px;
+
+      .pinyin-text {
+        display: flex;
+        flex-direction: column;
+        font-size: 24px;
+
+        .pinyin {
+          font-size: 12px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 13 - 0
src/components/RichText.vue

@@ -100,6 +100,10 @@ export default {
       type: Boolean,
       default: false,
     },
+    isViewPinyin: {
+      type: Boolean,
+      default: false,
+    },
   },
   data() {
     return {
@@ -378,9 +382,18 @@ export default {
     replaceSpanString(str) {
       return str.replace(/<span\b[^>]*>(.*?)<\/span>/gi, '$1');
     },
+    crateParsedTextInfoPinyin(content) {
+      let text = content.replace(/<[^>]+>/g, '');
+      this.$emit('crateParsedTextInfoPinyin', text);
+    },
     handleRichTextBlur() {
       this.$emit('handleRichTextBlur');
       let content = tinymce.get(this.id).getContent();
+      if (this.isViewPinyin) {
+        this.crateParsedTextInfoPinyin(content);
+        return;
+      }
+
       // 判断富文本中是否有 字母+数字+空格 的组合,如果没有,直接返回
       let isHasPinyin = content
         .split(/<[^>]+>/g)

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

@@ -0,0 +1,99 @@
+<template>
+  <el-dialog :visible="visible" width="260px" top="38vh" :show-close="false" @close="dialogClose">
+    <span class="tone-pinyin">{{ tonePinyin }}</span>
+    <span class="content-text">{{ selectContent }}</span>
+    <el-input v-model="numberPinyin" autocomplete="off" placeholder="请输入正确的拼音" @blur="convertTonePinyin" />
+    <span class="tips">一到四声分别用数字1-4表示,轻声用0表示。</span>
+    <template slot="footer">
+      <el-button size="medium" @click="dialogClose">取消</el-button>
+      <el-button type="primary" size="medium" @click="confirm">保存</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+import { addTone, handleToneValue } from '@/utils/common';
+export default {
+  name: 'CorrectPinyin',
+  props: {
+    visible: {
+      type: Boolean,
+      required: true,
+    },
+    selectContent: {
+      type: String,
+      required: true,
+    },
+  },
+  data() {
+    return {
+      tonePinyin: '',
+      numberPinyin: '',
+    };
+  },
+  methods: {
+    // 将数字拼音转换为声调拼音
+    convertTonePinyin() {
+      this.tonePinyin = this.numberPinyin
+        .trim()
+        .split(/\s+/)
+        .map((item) => {
+          return handleToneValue(item);
+        })
+        .map((item) =>
+          item.map(({ number, con }) => (number && con ? addTone(Number(number), con) : number || con || '')),
+        )
+        .filter((item) => item.length > 0)
+        .join(' ');
+      console.log(this.tonePinyin);
+    },
+    dialogClose() {
+      this.$emit('update:visible', false);
+    },
+    confirm() {
+      this.$emit('update:visible', false);
+      // this.$emit('fillTonePinyin', this.tonePinyin);
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.el-dialog {
+  :deep &__header {
+    padding: 0;
+  }
+
+  :deep &__body {
+    display: flex;
+    flex-direction: column;
+    row-gap: 8px;
+    align-items: center;
+    padding: 24px;
+
+    .tone-pinyin {
+      font-size: 20px;
+    }
+
+    .content-text {
+      margin-top: -12px;
+      font-size: 28px;
+    }
+
+    .tips {
+      font-size: 12px;
+      color: #a0a0a0;
+      text-align: left;
+    }
+  }
+
+  :deep &__footer {
+    display: flex;
+    padding: 8px;
+
+    .el-button {
+      flex: 1;
+    }
+  }
+}
+</style>

+ 50 - 3
src/views/book/courseware/create/components/base/describe/Describe.vue

@@ -1,26 +1,73 @@
 <template>
   <ModuleBase :type="data.type">
     <template #content>
-      <RichText v-model="data.content" :font-size="18" placeholder="输入描述" />
+      <RichText
+        ref="rich"
+        v-model="data.content"
+        :font-size="18"
+        placeholder="输入描述"
+        :is-view-pinyin="isEnable(data.property.view_pinyin)"
+        @crateParsedTextInfoPinyin="crateParsedTextInfoPinyin"
+      />
+      <el-divider v-if="isEnable(data.property.view_pinyin)" content-position="left">拼音效果展示</el-divider>
+      <PinyinText
+        v-if="isEnable(data.property.view_pinyin)"
+        :id="richId + '_pinyin_text'"
+        :paragraph-list="data.paragraph_list"
+        :pinyin-position="data.property.pinyin_position"
+      />
     </template>
   </ModuleBase>
 </template>
 
 <script>
 import { getDescribeData } from '@/views/book/courseware/data/describe';
+import { CrateParsedTextInfo_Pinyin } from '@/api/book';
+import { isEnable } from '@/views/book/courseware/data/common';
 import ModuleMixin from '../../common/ModuleMixin';
 import RichText from '@/components/RichText.vue';
+import PinyinText from '@/components/PinyinText.vue';
 
 export default {
   name: 'DescribePage',
-  components: { RichText },
+  components: { RichText, PinyinText },
   mixins: [ModuleMixin],
   data() {
     return {
+      isEnable,
       data: getDescribeData(),
+      selectContent: '',
+      richId: '',
     };
   },
-  methods: {},
+  watch: {
+    'data.property': {
+      handler(val) {
+        if (isEnable(val.view_pinyin)) {
+          let text = this.data.content.replace(/<[^>]+>/g, '');
+          this.crateParsedTextInfoPinyin(text);
+        }
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
+  methods: {
+    showSetting() {
+      this.richId = this.$refs.rich.id;
+      this.$emit('showSetting', this.data.property, this.data.type, this.id, {
+        richId: this.richId,
+      });
+    },
+    // 获取拼音解析文本
+    crateParsedTextInfoPinyin(text) {
+      CrateParsedTextInfo_Pinyin({ text }).then((res) => {
+        if (res.parsed_text) {
+          this.data.paragraph_list = res.parsed_text.paragraph_list;
+        }
+      });
+    },
+  },
 };
 </script>
 

+ 44 - 1
src/views/book/courseware/create/components/base/describe/DescribeSetting.vue

@@ -47,6 +47,8 @@
         <el-button type="primary">校对拼音</el-button>
       </el-form-item>
     </el-form>
+    <!--  @fillTonePinyin="fillTonePinyin" -->
+    <CorrectPinyin :visible.sync="visible" :select-content="selectContent" />
   </div>
 </template>
 
@@ -54,9 +56,14 @@
 import SettingMixin from '@/views/book/courseware/create/components/common/SettingMixin';
 import { viewMethodList, pinyinPositionList, snGenerationMethodList } from '@/views/book/courseware/data/common';
 import { getDescribeProperty } from '@/views/book/courseware/data/describe';
+import tinymce from 'tinymce/tinymce';
+import CorrectPinyin from '../common/CorrectPinyin.vue';
 
 export default {
   name: 'DescribeSetting',
+  components: {
+    CorrectPinyin,
+  },
   mixins: [SettingMixin],
   data() {
     return {
@@ -65,9 +72,45 @@ export default {
       snGenerationMethodList,
       labelPosition: 'left',
       property: getDescribeProperty(),
+      selectContent: '',
+      visible: false,
+      content: '',
     };
   },
-  methods: {},
+  methods: {
+    // 校对拼音
+    correctPinyin() {
+      let editor = tinymce.editors[this.param.richId];
+      let content = editor.selection.getContent();
+      if (content) {
+        this.visible = true;
+        this.selectContent = content;
+      }
+    },
+    // 回填校对后的拼音
+    // fillTonePinyin(tonePinyin) {
+    //   let richId = this.param.richId;
+    //   let editor = tinymce.editors[richId];
+    //   editor.selection.setContent(`${this.selectContent}(${tonePinyin})`);
+    //   this.searchText(editor, `${this.selectContent}(${tonePinyin})`);
+    //   debugger;
+    //   let pinyinText = document.getElementById(`${richId}_pinyin_text`);
+    //   const targetElements = pinyinText.querySelectorAll('.text');
+    //   let viewText = '';
+    //   targetElements.forEach((element) => {
+    //     viewText += element.innerText;
+    //   });
+    //   console.log(viewText);
+    // },
+    // searchText(editor, textToFind) {
+    //   const content = editor
+    //     .getContent()
+    //     .replace(/<[^>]+>/g, '')
+    //     .replace(/\n/g, '');
+    //   let index = content.indexOf(textToFind);
+    //   console.log(index);
+    // },
+  },
 };
 </script>
 

+ 46 - 3
src/views/book/courseware/create/components/base/stem/Stem.vue

@@ -1,26 +1,69 @@
 <template>
   <ModuleBase :type="data.type">
     <template #content>
-      <RichText v-model="data.content" :font-size="18" placeholder="输入题干" />
+      <RichText
+        ref="rich"
+        v-model="data.content"
+        :font-size="18"
+        placeholder="输入题干"
+        :is-view-pinyin="isEnable(data.property.view_pinyin)"
+        @crateParsedTextInfoPinyin="crateParsedTextInfoPinyin"
+      />
+      <el-divider v-if="isEnable(data.property.view_pinyin)" content-position="left">拼音效果展示</el-divider>
+      <PinyinText
+        v-if="isEnable(data.property.view_pinyin)"
+        :paragraph-list="data.paragraph_list"
+        :pinyin-position="data.property.pinyin_position"
+      />
     </template>
   </ModuleBase>
 </template>
 
 <script>
 import { getStemData } from '@/views/book/courseware/data/stem';
+import { CrateParsedTextInfo_Pinyin } from '@/api/book';
+import { isEnable } from '@/views/book/courseware/data/common';
 import ModuleMixin from '../../common/ModuleMixin';
 import RichText from '@/components/RichText.vue';
+import PinyinText from '@/components/PinyinText.vue';
 
 export default {
   name: 'StemPage',
-  components: { RichText },
+  components: { RichText, PinyinText },
   mixins: [ModuleMixin],
   data() {
     return {
+      isEnable,
       data: getStemData(),
     };
   },
-  methods: {},
+  watch: {
+    'data.property': {
+      handler(val) {
+        if (isEnable(val.view_pinyin)) {
+          let text = this.data.content.replace(/<[^>]+>/g, '');
+          this.crateParsedTextInfoPinyin(text);
+        }
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
+  methods: {
+    showSetting() {
+      this.$emit('showSetting', this.data.property, this.data.type, this.id, {
+        richId: this.$refs.rich.id,
+      });
+    },
+    // 获取拼音解析文本
+    crateParsedTextInfoPinyin(text) {
+      CrateParsedTextInfo_Pinyin({ text }).then((res) => {
+        if (res.parsed_text) {
+          this.data.paragraph_list = res.parsed_text.paragraph_list;
+        }
+      });
+    },
+  },
 };
 </script>
 

+ 20 - 0
src/views/book/courseware/data/common.js

@@ -46,6 +46,26 @@ export const arrangeTypeList = [
   { value: 'vertical', label: '竖排' },
 ];
 
+export const switchOption = [
+  {
+    value: 'true',
+    label: '开启',
+  },
+  {
+    value: 'false',
+    label: '关闭',
+  },
+];
+
+/**
+ * 是否开启
+ * @param {String} value 值
+ * @returns Boolean
+ */
+export function isEnable(value) {
+  return value === switchOption[0].value;
+}
+
 /**
  * 判断序号类型
  * @param {string} str

+ 2 - 0
src/views/book/courseware/data/describe.js

@@ -4,6 +4,7 @@ import {
   serialNumberPositionList,
   pinyinPositionList,
 } from '@/views/book/courseware/data/common';
+import tinymce from 'tinymce/tinymce';
 
 export function getDescribeProperty() {
   return {
@@ -25,6 +26,7 @@ export function getDescribeData() {
     type: 'describe',
     title: '描述',
     content: '',
+    paragraph_list: [],
     property: getDescribeProperty(),
   };
 }

+ 2 - 1
src/views/book/courseware/data/stem.js

@@ -24,7 +24,8 @@ export function getStemData() {
   return {
     type: 'stem',
     title: '题干',
-    stem: '',
+    content: '',
+    paragraph_list: [],
     property: getStemProperty(),
   };
 }

+ 10 - 1
src/views/book/courseware/preview/components/describe/DescribePreview.vue

@@ -2,7 +2,12 @@
   <div class="describe-preview" :style="getAreaStyle()">
     <SerialNumberPosition :property="data.property" />
     <div class="main">
-      <span class="rich-text" v-html="sanitizeHTML(data.content)"></span>
+      <PinyinText
+        v-if="isEnable(data.property.view_pinyin)"
+        :paragraph-list="data.paragraph_list"
+        :pinyin-position="data.property.pinyin_position"
+      />
+      <span v-else class="rich-text" v-html="sanitizeHTML(data.content)"></span>
     </div>
   </div>
 </template>
@@ -10,12 +15,16 @@
 <script>
 import { getDescribeData } from '@/views/book/courseware/data/describe';
 import PreviewMixin from '../common/PreviewMixin';
+import { isEnable } from '@/views/book/courseware/data/common';
+import PinyinText from '@/components/PinyinText.vue';
 
 export default {
   name: 'DescribePreview',
+  components: { PinyinText },
   mixins: [PreviewMixin],
   data() {
     return {
+      isEnable,
       data: getDescribeData(),
     };
   },

+ 10 - 1
src/views/book/courseware/preview/components/stem/StemPreview.vue

@@ -2,7 +2,12 @@
   <div class="stem-preview" :style="getAreaStyle()">
     <SerialNumberPosition :property="data.property" />
     <div class="main">
-      <span class="rich-text" v-html="sanitizeHTML(data.content)"></span>
+      <PinyinText
+        v-if="isEnable(data.property.view_pinyin)"
+        :paragraph-list="data.paragraph_list"
+        :pinyin-position="data.property.pinyin_position"
+      />
+      <span v-else class="rich-text" v-html="sanitizeHTML(data.content)"></span>
     </div>
   </div>
 </template>
@@ -10,12 +15,16 @@
 <script>
 import { getStemData } from '@/views/book/courseware/data/stem';
 import PreviewMixin from '../common/PreviewMixin';
+import { isEnable } from '@/views/book/courseware/data/common';
+import PinyinText from '@/components/PinyinText.vue';
 
 export default {
   name: 'StemPreview',
+  components: { PinyinText },
   mixins: [PreviewMixin],
   data() {
     return {
+      isEnable,
       data: getStemData(),
     };
   },