Browse Source

输入框与富文本多语言,将多言语变为公用,并优化

dsy 4 days ago
parent
commit
0e083e7434

+ 6 - 0
src/icons/svg/multilingual.svg

@@ -0,0 +1,6 @@
+<svg t="1755036112589" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4003"
+  width="200" height="200">
+  <path
+    d="M710.8608 389.12c3.8912 39.3728 5.9392 80.5376 5.9392 122.88s-2.048 83.5072-5.9392 122.88h213.4016c11.5712-38.912 17.8176-80.1792 17.8176-122.88 0-42.7008-6.2464-83.968-17.8176-122.88h-213.4016z m-82.5344 0H395.6736a1147.392 1147.392 0 0 0 0 245.76h232.6528a1147.392 1147.392 0 0 0 0-245.76z m-315.1872 0H99.7376A430.1312 430.1312 0 0 0 81.92 512c0 42.7008 6.2464 83.968 17.8176 122.88h213.4016A1255.7312 1255.7312 0 0 1 307.2 512c0-42.3424 2.048-83.5072 5.9392-122.88z m320.0512 535.6544A431.2064 431.2064 0 0 0 890.2656 716.8h-190.464c-14.592 83.2-37.6832 154.8288-66.56 207.9744z m-242.3808 0c-28.928-53.1456-52.0192-124.7744-66.56-207.9744H133.7344a431.2064 431.2064 0 0 0 257.024 207.9744zM407.7056 716.8c25.4464 135.168 71.5776 225.28 104.2944 225.28s78.848-90.112 104.2432-225.28H407.7568z m225.4848-617.5744c28.928 53.1456 52.0192 124.7744 66.56 207.9744h190.5152a431.2064 431.2064 0 0 0-257.024-207.9744z m-242.3808 0A431.2064 431.2064 0 0 0 133.7344 307.2h190.464c14.592-83.2 37.6832-154.8288 66.56-207.9744zM407.7056 307.2h208.5376C590.848 172.032 544.768 81.92 512 81.92S433.152 172.032 407.7568 307.2zM512 1024C229.2224 1024 0 794.7776 0 512S229.2224 0 512 0s512 229.2224 512 512-229.2224 512-512 512z"
+    fill="currentColor" p-id="4004"></path>
+</svg>

+ 4 - 0
src/styles/mixin.scss

@@ -64,6 +64,10 @@
   .main {
     grid-area: main;
     width: 100%;
+
+    .lang {
+      grid-area: lang;
+    }
   }
 }
 

+ 10 - 0
src/views/book/components/MultilingualFill.vue

@@ -116,6 +116,16 @@ export default {
       },
       immediate: true,
     },
+    visible: {
+      handler(newVal) {
+        if (!newVal && this.selectedLangList.length > 0) {
+          this.selectedLangList = this.selectedLangList.map((item) => ({
+            code: item.code,
+            translation: '',
+          }));
+        }
+      },
+    },
   },
   methods: {
     closeDialog() {

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

@@ -15,6 +15,14 @@
           @compareAnnotationAndSave="compareAnnotationAndSave"
         />
         <el-divider v-if="isEnable(data.property.view_pinyin)" content-position="left">拼音效果</el-divider>
+
+        <el-button class="btn" @click="openMultilingual">多语言</el-button>
+        <MultilingualFill
+          :visible.sync="multilingualVisible"
+          :text="data.content"
+          :translations="data.multilingual"
+          @SubmitTranslation="handleMultilingualTranslation"
+        />
         <PinyinText
           v-if="isEnable(data.property.view_pinyin)"
           :id="richId + '_pinyin_text'"
@@ -27,7 +35,7 @@
       <ExplanatoryNoteDialog
         ref="explanatoryNote"
         :open.sync="isViewExplanatoryNoteDialog"
-        :initData="oldRichData"
+        :init-data="oldRichData"
         @confirm="confirmExplanatoryNote"
         @cancel="cancelExplanatoryNote"
       />
@@ -185,3 +193,9 @@ export default {
   },
 };
 </script>
+
+<style lang="scss" scoped>
+.btn {
+  margin-top: 12px;
+}
+</style>

+ 13 - 0
src/views/book/courseware/create/components/common/ModuleMixin.js

@@ -2,6 +2,7 @@
 import Vue from 'vue';
 import ModuleBase from './ModuleBase.vue';
 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';
@@ -16,6 +17,7 @@ const mixin = {
         isGetContent: false, // 是否已获取内容
       },
       borderColorObj: Vue.observable({ value: this.borderColor }), // 边框颜色
+      multilingualVisible: false, // 多语言弹窗
     };
   },
   props: {
@@ -39,6 +41,7 @@ const mixin = {
   components: {
     ModuleBase,
     RichText,
+    MultilingualFill,
   },
   provide() {
     return {
@@ -124,6 +127,16 @@ const mixin = {
       }
       return null;
     },
+    openMultilingual() {
+      this.multilingualVisible = true;
+    },
+    /**
+     * @description 提交多语言翻译
+     * @param {Array} multilingual
+     */
+    handleMultilingualTranslation(multilingual) {
+      this.data.multilingual = multilingual;
+    },
   },
 };
 

+ 1 - 11
src/views/book/courseware/create/components/question/fill/Fill.vue

@@ -42,7 +42,7 @@
 
         <div>
           <el-button @click="identifyText">识别</el-button>
-          <el-button @click="multilingualVisible = true">多语言</el-button>
+          <el-button @click="openMultilingual">多语言</el-button>
         </div>
 
         <div class="correct-answer">
@@ -71,7 +71,6 @@
 import ModuleMixin from '../../common/ModuleMixin';
 import SoundRecord from '@/views/book/courseware/create/components/question/fill/components/SoundRecord.vue';
 import UploadAudio from '@/views/book/courseware/create/components/question/fill/components/UploadAudio.vue';
-import MultilingualFill from '@/views/book/components/MultilingualFill.vue';
 
 import { getFillData, arrangeTypeList, fillFontList, fillTypeList } from '@/views/book/courseware/data/fill';
 import { addTone, handleToneValue } from '@/views/book/courseware/data/common';
@@ -83,14 +82,12 @@ export default {
   components: {
     SoundRecord,
     UploadAudio,
-    MultilingualFill,
   },
   mixins: [ModuleMixin],
   data() {
     return {
       data: getFillData(),
       fillTypeList,
-      multilingualVisible: false,
     };
   },
   watch: {
@@ -213,13 +210,6 @@ export default {
         },
       ];
     },
-    /**
-     * @description 提交多语言翻译
-     * @param {Array} multilingual
-     */
-    handleMultilingualTranslation(multilingual) {
-      this.data.multilingual = multilingual;
-    },
   },
 };
 </script>

+ 14 - 1
src/views/book/courseware/create/components/question/input/Input.vue

@@ -8,6 +8,14 @@
         :font-size="18"
         placeholder="请输入内容"
       />
+
+      <el-button class="btn" @click="openMultilingual">多语言</el-button>
+      <MultilingualFill
+        :visible.sync="multilingualVisible"
+        :text="data.content"
+        :translations="data.multilingual"
+        @SubmitTranslation="handleMultilingualTranslation"
+      />
     </template>
   </ModuleBase>
 </template>
@@ -42,10 +50,15 @@ export default {
         },
       ];
     },
+    handleMultilingualTranslation(translations) {
+      this.data.multilingual = translations;
+    },
   },
 };
 </script>
 
 <style lang="scss" scoped>
-@use '@/styles/mixin.scss' as *;
+.btn {
+  margin-top: 12px;
+}
 </style>

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

@@ -10,6 +10,9 @@
             </span>
             <RichText v-model="item.content" placeholder="输入内容" :inline="true" :height="32" />
           </div>
+          <span class="multilingual" @click="openMultilingual(i)">
+            <SvgIcon icon-class="multilingual" class-name="multilingual" width="12" height="12" />
+          </span>
           <span class="delete" @click="deleteOption">
             <SvgIcon icon-class="delete-2" width="12" height="12" />
           </span>
@@ -19,6 +22,14 @@
         <SvgIcon icon-class="add-circle" width="14" height="14" />
         <span class="add-button" @click="addOption">增加选项</span>
       </div>
+
+      <MultilingualFill
+        v-if="curSelectIndex !== -1"
+        :visible.sync="multilingualVisible"
+        :text="data.option_list[curSelectIndex].content"
+        :translations="data.option_list[curSelectIndex].multilingual"
+        @SubmitTranslation="handleMultilingualTranslation"
+      />
     </template>
   </ModuleBase>
 </template>
@@ -34,6 +45,7 @@ export default {
   data() {
     return {
       data: getSelectData(),
+      curSelectIndex: -1,
     };
   },
   watch: {
@@ -82,6 +94,13 @@ export default {
       const select = this.data.answer.answer_list.length > 1 ? '多选' : '单选';
       this.data.mind_map.node_list = [{ name: `${direction}${select}选择题` }];
     },
+    openMultilingual(i) {
+      this.curSelectIndex = i;
+      this.multilingualVisible = true;
+    },
+    handleMultilingualTranslation(translations) {
+      this.$set(this.data.option_list[this.curSelectIndex], 'multilingual', translations);
+    },
   },
 };
 </script>
@@ -142,7 +161,8 @@ export default {
       }
     }
 
-    .delete {
+    .delete,
+    .multilingual {
       margin-left: 8px;
       cursor: pointer;
     }

+ 1 - 0
src/views/book/courseware/data/input.js

@@ -111,5 +111,6 @@ export function getInputData() {
         },
       ],
     },
+    multilingual: [], // 多语言
   };
 }

+ 1 - 0
src/views/book/courseware/data/richText.js

@@ -476,5 +476,6 @@ export function getRichTextData() {
     mind_map: {
       node_list: [{ name: '富文本' }],
     },
+    multilingual: [], // 多语言
   };
 }

+ 1 - 0
src/views/book/courseware/data/select.js

@@ -25,6 +25,7 @@ export function getOption() {
   return {
     content: '',
     mark: getRandomNumber(),
+    multilingual: [], // 多语言
   };
 }
 

+ 15 - 0
src/views/book/courseware/preview/components/dialogue_article/RemarkChs.vue

@@ -0,0 +1,15 @@
+<template>
+  <div></div>
+</template>
+
+<script>
+export default {
+  name: 'RemarkChs',
+  data() {
+    return {};
+  },
+  methods: {},
+};
+</script>
+
+<style lang="scss" scoped></style>

+ 15 - 0
src/views/book/courseware/preview/components/dialogue_article/RoleChs.vue

@@ -0,0 +1,15 @@
+<template>
+  <div></div>
+</template>
+
+<script>
+export default {
+  name: 'RoleChs',
+  data() {
+    return {};
+  },
+  methods: {},
+};
+</script>
+
+<style lang="scss" scoped></style>

+ 0 - 4
src/views/book/courseware/preview/components/fill/FillPreview.vue

@@ -314,10 +314,6 @@ export default {
   .main {
     display: grid;
     align-items: center;
-
-    .lang {
-      grid-area: lang;
-    }
   }
 
   .fill-wrapper {

+ 22 - 5
src/views/book/courseware/preview/components/input/InputPreview.vue

@@ -3,7 +3,7 @@
   <div class="input-preview" :style="getAreaStyle()">
     <SerialNumberPosition v-if="isEnable(data.property.sn_display_mode)" :property="data.property" />
 
-    <div class="main">
+    <div class="main" :style="getMainStyle()">
       <span class="rich-text" v-html="sanitizeHTML(data.content)"></span>
       <el-input
         ref="input"
@@ -21,6 +21,9 @@
         ]"
         @change="onInputChange"
       />
+      <div v-show="showLang" class="lang">
+        {{ data.multilingual.find((item) => item.code === getLang())?.translation }}
+      </div>
     </div>
   </div>
 </template>
@@ -75,6 +78,11 @@ export default {
       }
       this.data.answer.text = answer;
     },
+    getMainStyle() {
+      return {
+        gridTemplateAreas: this.showLang ? "'rich input' 'lang lang'" : "'rich input'",
+      };
+    },
   },
 };
 </script>
@@ -86,12 +94,21 @@ export default {
   @include preview-base;
 
   .main {
-    display: flex;
-    column-gap: 4px;
+    display: grid;
+    grid-template-columns: auto 1fr;
+    gap: 4px;
     align-items: center;
 
-    .rich-text :deep p {
-      word-break: keep-all;
+    .rich-text {
+      grid-area: rich;
+
+      :deep p {
+        word-break: keep-all;
+      }
+    }
+
+    .input {
+      grid-area: input;
     }
 
     .input.input-horizontal :deep .el-input__inner {

+ 7 - 2
src/views/book/courseware/preview/components/rich_text/RichTextPreview.vue

@@ -12,19 +12,23 @@
         />
         <span v-else class="rich-text" @click="handleRichFillClick" v-html="sanitizeHTML(data.content)"></span>
       </div>
+
+      <div v-show="showLang" class="lang">
+        {{ data.multilingual.find((item) => item.code === getLang())?.translation }}
+      </div>
     </div>
 
     <el-dialog
+      ref="optimizedDialog"
       title=""
       :visible.sync="noteDialogVisible"
       width="680px"
-      ref="optimizedDialog"
       :style="dialogStyle"
       :close-on-click-modal="false"
       destroy-on-close
       @close="noteDialogVisible = false"
     >
-      <span v-html="selectedNote"></span>
+      <span v-html="sanitizeHTML(selectedNote)"></span>
     </el-dialog>
   </div>
 </template>
@@ -151,6 +155,7 @@ export default {
     position: fixed;
     margin: 0 !important;
     transition: all 0.2s; /* 添加平滑过渡效果 */
+
     .el-dialog__header {
       padding: 0 !important;
 

+ 0 - 3
src/views/personal_workbench/edit_task/edit/index.vue

@@ -41,8 +41,6 @@
 </template>
 
 <script>
-import Vue from 'vue';
-
 import CreatePage from '@/views/book/courseware/create/index.vue';
 import MenuPage from '@/views/personal_workbench/common/menu.vue';
 import * as OpenCC from 'opencc-js';
@@ -56,7 +54,6 @@ export default {
     CreatePage,
     MenuPage,
   },
-  // 将 lang、chinese 提供给子组件,并让这几个属性可响应式
   provide() {
     return {
       getLang: () => this.lang,