فهرست منبع

选择声调预览

natasha 1 سال پیش
والد
کامیت
5b3efe82e7

+ 1 - 1
src/icons/svg/first-tone.svg

@@ -1,3 +1,3 @@
 <svg width="14" height="4" viewBox="0 0 14 4" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M2 2H12" stroke="#4E5969" stroke-width="2.5" stroke-linecap="round"/>
+<path d="M2 2H12" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"/>
 </svg>

+ 2 - 2
src/icons/svg/fourth-tone.svg

@@ -1,3 +1,3 @@
-<svg width="14" height="8" viewBox="0 0 14 8" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M2 2L6.2948 5.86532C6.69013 6.22111 7.29479 6.20521 7.67087 5.82913L12 1.5" stroke="#4E5969" stroke-width="2.5" stroke-linecap="round"/>
+<svg width="12" height="8" viewBox="0 0 12 8" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M1.75977 1.35059L10.2402 6.64978" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"/>
 </svg>

+ 1 - 1
src/icons/svg/neutral-tone.svg

@@ -1,3 +1,3 @@
 <svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
-<circle cx="6" cy="6" r="4.25" stroke="#4E5969" stroke-width="2.5"/>
+<circle cx="6" cy="6" r="4.25" stroke="currentColor" stroke-width="2.5"/>
 </svg>

+ 1 - 1
src/icons/svg/second-tone.svg

@@ -1,3 +1,3 @@
 <svg width="12" height="8" viewBox="0 0 12 8" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M1.75977 6.64941L10.2402 1.35022" stroke="#4E5969" stroke-width="2.5" stroke-linecap="round"/>
+<path d="M1.75977 6.64941L10.2402 1.35022" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"/>
 </svg>

+ 2 - 2
src/icons/svg/third-tone.svg

@@ -1,3 +1,3 @@
-<svg width="12" height="8" viewBox="0 0 12 8" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M1.75977 1.35059L10.2402 6.64978" stroke="#4E5969" stroke-width="2.5" stroke-linecap="round"/>
+<svg width="14" height="8" viewBox="0 0 14 8" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2 2L6.2948 5.86532C6.69013 6.22111 7.29479 6.20521 7.67087 5.82913L12 1.5" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"/>
 </svg>

+ 8 - 2
src/views/exercise_questions/create/components/exercises/ChooseToneQuestion.vue

@@ -193,10 +193,10 @@ export default {
     handleItemAnswer(item) {
       const index = this.data.answer.select_list.findIndex((items) => items.mark === item.mark);
       let content = item.content.trim();
-      let contentArr = content.split(' ');
+      let content_arr = content.split(' ');
       let select_item = '';
       let content_preview = '';
-      contentArr.forEach((items) => {
+      content_arr.forEach((items) => {
         let items_trim = items.trim();
         if (items_trim) {
           let items_yuan = JSON.parse(JSON.stringify(items_trim)).replace(/0|1|2|3|4/, '');
@@ -303,6 +303,12 @@ export default {
         cursor: pointer;
       }
     }
+
+    .delete {
+      flex-shrink: 0;
+      width: 16px;
+      height: 16px;
+    }
   }
 }
 </style>

+ 170 - 10
src/views/exercise_questions/preview/ChooseTonePreview.vue

@@ -11,12 +11,26 @@
       <li v-for="(item, i) in data.option_list" :key="i" :class="['option-item', { active: isAnswer(item.mark) }]">
         <span>{{ computeOptionMethods[data.option_number_show_mode](i) }}. </span>
         <AudioPlay v-if="item.audio_file_id" :file-id="item.audio_file_id" />
-        <div class="option-content" v-html="sanitizeHTML(item.content)"></div>
+        <div class="option-content">
+          <template v-if="data.property.tone_type === 'select'">
+            <span
+              v-for="(itemc, indexc) in con_preview[i].item_con"
+              :key="indexc"
+              :class="['item-con']"
+              @click="con_preview[i].item_active_index = indexc"
+            >
+              {{ itemc }}
+            </span>
+          </template>
+        </div>
         <span
           v-for="({ img, value }, j) in toneList"
           :key="j"
-          :class="['tone', item.tone === value ? 'active' : '']"
-          @click="chooseTone(item, value)"
+          :class="[
+            'tone',
+            con_preview[i].user_answer[con_preview[i].item_active_index].select_tone === value ? 'active' : '',
+          ]"
+          @click="chooseTone(con_preview[i], value)"
         >
           <SvgIcon :icon-class="img" />
         </span>
@@ -36,23 +50,165 @@ export default {
     return {
       computeOptionMethods,
       toneList: [
-        { value: 'first', label: '一声', img: 'first-tone' },
-        { value: 'second', label: '二声', img: 'second-tone' },
-        { value: 'third', label: '三声', img: 'third-tone' },
-        { value: 'fourth', label: '四声', img: 'fourth-tone' },
-        { value: 'neutral', label: '轻声', img: 'neutral-tone' },
+        { value: '1', label: '一声', img: 'first-tone' },
+        { value: '2', label: '二声', img: 'second-tone' },
+        { value: '3', label: '三声', img: 'third-tone' },
+        { value: '4', label: '四声', img: 'fourth-tone' },
+        { value: '0', label: '轻声', img: 'neutral-tone' },
       ],
+      con_preview: [],
+      tone_data: [
+        ['ā', 'á', 'ǎ', 'à', 'a'],
+        ['ō', 'ó', 'ǒ', 'ò', 'o'],
+        ['ē', 'é', 'ě', 'è', 'e'],
+        ['ī', 'í', 'ǐ', 'ì', 'i'],
+        ['ū', 'ú', 'ǔ', 'ù', 'u'],
+        ['ǖ', 'ǘ', 'ǚ', 'ǜ', 'ü'],
+        ['Ā', 'Á', 'Â', 'À', 'A'],
+        ['Ō', 'Ó', 'Ô', 'Ò', 'O'],
+        ['Ē', 'É', 'Ê', 'È', 'E'],
+        ['Ī', 'Í', 'Î', 'Ì', 'I'],
+        ['Ū', 'Ú', 'Û', 'Ù', 'U'],
+      ],
+      final_con: '',
     };
   },
   created() {
-    console.log(this.data);
+    this.handleData();
   },
   methods: {
     isAnswer(mark, option_type) {
       return this.answer.select_list.some((li) => li.mark === mark && li.option_type === option_type);
     },
     chooseTone(item, value) {
-      item.tone = value;
+      item.user_answer[item.item_active_index].select_tone = value;
+      if (this.data.property.tone_type === 'dimension') {
+        item.user_answer[item.item_active_index].select_letter = item.user_answer[item.item_active_index].active_letter;
+      }
+      this.handleReplaceTone(item.item_con_yuan[item.item_active_index] + value);
+
+      setTimeout(() => {
+        item.item_con[item.item_active_index] = this.final_con;
+        this.$forceUpdate();
+      }, 100);
+    },
+    // 处理数据
+    handleData() {
+      this.con_preview = [];
+      this.data.option_list.forEach((item) => {
+        let con_arr = item.content_preview.split(' ');
+        let user_answer = [];
+        con_arr.forEach(() => {
+          user_answer.push({
+            select_tone: null,
+            select_letter: '',
+          });
+        });
+        let obj = {
+          item_con: con_arr,
+          item_con_yuan: JSON.parse(JSON.stringify(con_arr)),
+          mark: item.mark,
+          user_answer,
+          item_active_index: 0,
+          active_letter: '',
+        };
+        this.con_preview.push(obj);
+      });
+      console.log(this.con_preview);
+    },
+    handleReplaceTone(e) {
+      this.$nextTick(() => {
+        let value = e;
+        this.resArr = [];
+        if (value) {
+          let reg = /\s+/g;
+          let valueArr = value.split(reg);
+          valueArr.forEach((item) => {
+            this.handleValue(item);
+          });
+          let str = '';
+          setTimeout(() => {
+            this.resArr.forEach((item) => {
+              str += ' ';
+              item.forEach((sItem) => {
+                if (sItem.number && sItem.con) {
+                  let number = Number(sItem.number);
+                  let con = sItem.con;
+                  let word = this.addTone(number, con);
+                  str += word;
+                } else if (sItem.number) {
+                  str += sItem.number;
+                } else if (sItem.con) {
+                  str += ` ${sItem.con} `;
+                }
+              });
+            });
+            this.final_con = str.trim();
+          }, 10);
+        }
+      });
+    },
+    handleValue(valItem) {
+      let reg = /\d/;
+      let reg2 = /[A-Za-z]+\d/g;
+      let numList = [];
+      let valArr = valItem.split('');
+      if (reg2.test(valItem)) {
+        for (let i = 0; i < valArr.length; i++) {
+          let item = valItem[i];
+          if (reg.test(item)) {
+            let numIndex = numList.length === 0 ? 0 : numList[numList.length - 1].index;
+            let con = valItem.substring(numIndex, i);
+            con = con.replace(/\d/g, '');
+            let obj = {
+              index: i,
+              number: item,
+              con,
+              isTran: true,
+            };
+            numList.push(obj);
+          }
+        }
+      } else {
+        numList = [];
+      }
+      if (numList.length === 0) {
+        this.resArr.push([{ con: valItem }]);
+      } else {
+        this.resArr.push(numList);
+      }
+    },
+    addTone(number, con) {
+      let zmList = ['a', 'o', 'e', 'i', 'u', 'v', 'A', 'O', 'E', 'I', 'U'];
+      let cons = con;
+      if (number) {
+        for (let i = 0; i < zmList.length; i++) {
+          let zm = zmList[i];
+          if (con.indexOf(zm) > -1) {
+            let zm2 = this.tone_data[i][number - 1];
+            if (con.indexOf('iu') > -1) {
+              zm2 = this.tone_data[4][number - 1];
+              cons = con.replace('u', zm2);
+            } else if (con.indexOf('ui') > -1) {
+              zm2 = this.tone_data[3][number - 1];
+              cons = con.replace('i', zm2);
+            } else if (
+              con.indexOf('yv') > -1 ||
+              con.indexOf('jv') > -1 ||
+              con.indexOf('qv') > -1 ||
+              con.indexOf('xv') > -1
+            ) {
+              zm2 = this.tone_data[4][number - 1];
+              cons = con.replace('v', zm2);
+            } else {
+              cons = con.replace(zm, zm2);
+            }
+
+            break;
+          }
+        }
+      }
+      return cons;
     },
   },
 };
@@ -84,6 +240,10 @@ export default {
         border-radius: 40px;
       }
 
+      .item-con {
+        cursor: pointer;
+      }
+
       .tone {
         width: 32px;
         height: 32px;