Prechádzať zdrojové kódy

注释组件添加图片

natasha 2 dní pred
rodič
commit
92dfbc8962

+ 4 - 0
src/views/book/courseware/create/components/question/new_word/components/UploadPicture.vue

@@ -142,4 +142,8 @@ export default {
     }
   }
 }
+
+.delete {
+  flex-shrink: 0;
+}
 </style>

+ 133 - 4
src/views/book/courseware/create/components/question/notes/Notes.vue

@@ -10,13 +10,13 @@
         toolbar="fontselect fontsizeselect forecolor backcolor | underline | bold italic strikethrough alignleft aligncenter alignright"
         class="title-box"
       />
-      <el-table :data="data.option" border style="width: 100%">
-        <el-table-column fixed prop="number" label="序号" width="70">
+      <el-table :data="data.option" :key="refreshKey" border style="width: 100%">
+        <el-table-column 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 prop="con" label="内容" width="200">
           <template slot-scope="scope">
             <RichText
               ref="richText"
@@ -47,6 +47,18 @@
             />
           </template>
         </el-table-column>
+        <el-table-column prop="img_list" label="图片">
+          <template slot-scope="scope">
+            <UploadPicture
+              :file-id="scope.row.file_list[0]"
+              :item-index="scope.$index"
+              :show-upload="!scope.row.file_list[0]"
+              @upload="uploadPic"
+              @deleteFile="deletePic"
+            />
+          </template>
+        </el-table-column>
+
         <el-table-column label="操作" width="150">
           <template slot-scope="scope">
             <el-button size="mini" type="text" @click="handleDelete(scope.$index)">删除</el-button>
@@ -63,27 +75,80 @@
         :translations="data.multilingual"
         @SubmitTranslation="handleMultilingualTranslation"
       />
+      <el-divider v-if="isEnable(data.property.view_pinyin)" content-position="left">拼音效果</el-divider>
+      <PinyinText
+        v-if="isEnable(data.property.view_pinyin)"
+        :id="'table_pinyin_text'"
+        ref="PinyinText"
+        :paragraph-list="data.paragraph_list"
+        :pinyin-position="data.property.pinyin_position"
+        @fillCorrectPinyin="fillCorrectPinyin"
+      />
     </template>
   </ModuleBase>
 </template>
 
 <script>
+import { isEnable } from '@/views/book/courseware/data/common';
 import ModuleMixin from '../../common/ModuleMixin';
+import { CrateParsedTextInfo_Pinyin } from '@/api/book';
+import PinyinText from '@/components/PinyinText.vue';
+import UploadPicture from '../new_word/components/UploadPicture.vue';
 
 import { getNotesData, getOption } from '@/views/book/courseware/data/notes';
 
 export default {
   name: 'NotesPage',
-  components: {},
+  components: { PinyinText, UploadPicture },
   mixins: [ModuleMixin],
   data() {
     return {
+      isEnable,
       data: getNotesData(),
       multilingualText: '',
+      refreshKey: '',
     };
   },
   watch: {
     'data.option': 'handleMindMap',
+    'data.property.view_pinyin': {
+      handler(val) {
+        let text = '';
+        this.data.option.forEach((item) => {
+          text += `${item.con.replace(/<[^>]+>/g, '')}\n`;
+        });
+        if (!isEnable(val)) {
+          this.data.paragraph_list = [];
+          return;
+        }
+        if (isEnable(val) && text && this.data.paragraph_list.length <= 0) {
+          this.data.paragraph_list_parameter.text = text;
+          this.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;
+          this.createParsedTextInfoPinyin(text);
+        }
+      },
+      deep: true,
+    },
+    'data.property.is_first_sentence_first_hz_pinyin_first_char_upper_case': {
+      handler(val, oldVal) {
+        if (val === oldVal) return;
+        let text = '';
+        this.data.option.forEach((item) => {
+          text += `${item.con.replace(/<[^>]+>/g, '')}\n`;
+        });
+        if (!isEnable(this.data.property.view_pinyin)) {
+          this.data.paragraph_list = [];
+          return;
+        }
+        if (text && isEnable(this.data.property.view_pinyin)) {
+          this.data.paragraph_list_parameter.text = text;
+          this.data.paragraph_list_parameter.is_first_sentence_first_hz_pinyin_first_char_upper_case = val;
+          this.createParsedTextInfoPinyin(text);
+        }
+      },
+      deep: true,
+    },
   },
   methods: {
     // 删除行
@@ -127,6 +192,70 @@ export default {
       });
       this.multilingualVisible = true;
     },
+    // 获取拼音解析文本
+    createParsedTextInfoPinyin(text) {
+      if (text === '') {
+        this.data.paragraph_list_parameter.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 =
+        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) =>
+            outerArr.map((innerArr, j) =>
+              innerArr.map((newItem, k) => {
+                // 从 originalData 中找到对应的项
+                const originalItem = this.data.paragraph_list[i]?.[j];
+
+                // 如果 originalItem 有 activeTextStyle,就合并到 newItem
+                if (originalItem?.activeTextStyle) {
+                  return {
+                    ...newItem,
+                    activeTextStyle: originalItem.activeTextStyle,
+                  };
+                }
+                // 否则直接返回 newItem
+                return newItem;
+              }),
+            ),
+          );
+          this.data.paragraph_list = mergedData;
+          let pinyin_index = 0;
+          this.data.option.forEach((items, index) => {
+            items.model_pinyin = [];
+            if (items.content && mergedData[pinyin_index] && mergedData[pinyin_index][0]) {
+              mergedData[pinyin_index][0].forEach((itemP) => {
+                items.model_pinyin.push(itemP);
+              });
+              pinyin_index++;
+            }
+          });
+        }
+      });
+    },
+    // 填充校对后的拼音
+    fillCorrectPinyin({ selectContent: { text, pinyin, activeTextStyle }, i, j }) {
+      this.data.paragraph_list_parameter.pinyin_proofread_word_list.push({
+        paragraph_index: i,
+        sentence_index: j,
+        word_index: k,
+        word: text,
+        pinyin,
+      });
+      if (pinyin) this.data.paragraph_list[i][j].pinyin = pinyin;
+      if (activeTextStyle) this.data.paragraph_list[i][j].activeTextStyle = activeTextStyle;
+    },
+    uploadPic(file_id, index) {
+      this.data.option[index].file_list[0] = file_id;
+      this.data.file_id_list.push(file_id);
+      this.refreshKey = Math.random();
+    },
+    deletePic(file_id, index) {
+      this.data.option[index].file_list[0] = '';
+      this.data.file_id_list = this.data.file_id_list.filter((item) => item !== file_id);
+    },
   },
 };
 </script>

+ 27 - 1
src/views/book/courseware/create/components/question/notes/NotesSetting.vue

@@ -9,6 +9,29 @@
           </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 label="拼音位置">
+        <el-radio
+          v-for="{ value, label } in pinyinPositionLists"
+          :key="value"
+          v-model="property.pinyin_position"
+          :label="value"
+          :disabled="!isEnable(property.view_pinyin)"
+        >
+          {{ label }}
+        </el-radio>
+      </el-form-item>
+      <el-form-item 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>
@@ -16,15 +39,18 @@
 <script>
 import SettingMixin from '@/views/book/courseware/create/components/common/SettingMixin';
 
-import { getNotesProperty, wordShowList } from '@/views/book/courseware/data/notes';
+import { getNotesProperty, wordShowList, pinyinPositionLists } from '@/views/book/courseware/data/notes';
+import { isEnable } from '@/views/book/courseware/data/common';
 
 export default {
   name: 'NotesSetting',
   mixins: [SettingMixin],
   data() {
     return {
+      isEnable,
       property: getNotesProperty(),
       wordShowList,
+      pinyinPositionLists,
     };
   },
   methods: {},

+ 20 - 1
src/views/book/courseware/data/notes.js

@@ -9,6 +9,14 @@ import {
 
 export { arrangeTypeList, switchOption, isEnable };
 
+// 拼音位置
+export const pinyinPositionLists = [
+  { value: 'front', label: '前面' },
+  { value: 'back', label: '后面' },
+  { value: 'top', label: '上面' },
+  { value: 'bottom', label: '下面' },
+];
+
 export const wordShowList = [
   { value: 'true', label: '是' },
   { value: 'false', label: '否' },
@@ -20,7 +28,7 @@ export function getOption() {
     con: '',
     interpret: '', // 翻译
     note: '', // 注释
-    img_list: [],
+    file_list: [''], // 图片
   };
 }
 export function getNotesProperty() {
@@ -30,6 +38,9 @@ export function getNotesProperty() {
     sn_position: serialNumberPositionList[3].value,
     sn_display_mode: displayList[0].value,
     is_word_show: wordShowList[0].value,
+    view_pinyin: 'false', // 显示拼音
+    pinyin_position: pinyinPositionLists[1].value, // top bottom
+    is_first_sentence_first_hz_pinyin_first_char_upper_case: 'true', // 句首大写
   };
 }
 
@@ -40,11 +51,19 @@ export function getNotesData() {
     property: getNotesProperty(),
     title_con: '',
     option: [getOption()],
+    file_id_list: [], // 文件 id
     mind_map: {
       node_list: [
         { name: '注释组件' }
       ], // 思维导图数据
     },
+    paragraph_list: [],
+    paragraph_list_parameter: {
+      text: '',
+      is_first_sentence_first_hz_pinyin_first_char_upper_case: 'true',
+      pinyin_proofread_word_list: [],
+    },
     multilingual: [], // 多语言
+
   };
 }

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

@@ -35,11 +35,10 @@
                 </span>
               </div>
               <div class="NPC-notes-trans" v-html="item.interpret"></div>
+
               <div v-if="item.note" class="NPC-notes-note" v-html="item.note"></div>
-              <div v-if="item.img_list && item.img_list.length > 0" class="NPC-notes-note-img">
-                <div v-for="(imgItem, imgIndex) in item.img_list" :key="'imgList' + imgIndex">
-                  <img :src="imgItem.id" class="NPC-notes-img" />
-                </div>
+              <div v-if="item.file_list[0]" class="NPC-notes-note-img">
+                <el-image :src="item.pic_url" :preview-src-list="[item.pic_url]" fit="contain" />
               </div>
               <div class="NPC-notes-note" v-if="showLang">
                 {{
@@ -62,6 +61,7 @@
 import { getNotesData, isEnable } from '@/views/book/courseware/data/notes';
 
 import PreviewMixin from '../common/PreviewMixin';
+import { GetFileURLMap } from '@/api/app';
 
 export default {
   name: 'NotesPreview',
@@ -112,6 +112,13 @@ export default {
           this.$set(this.multilingualTextList, item.type, chunkedArr);
         });
       }
+      this.data.option.forEach((item) => {
+        if (item.file_list && item.file_list[0]) {
+          GetFileURLMap({ file_id_list: item.file_list }).then(({ url_map }) => {
+            this.$set(item, 'pic_url', url_map[item.file_list[0]]);
+          });
+        }
+      });
     },
   },
 };
@@ -248,7 +255,7 @@ export default {
       width: 100%;
 
       > div {
-        width: 100%;
+        max-width: 100%;
 
         > img {
           max-width: 100%;