Browse Source

选择声调

natasha 1 year ago
parent
commit
38ee38a051

+ 3 - 0
src/icons/svg/reset.svg

@@ -0,0 +1,3 @@
+<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M3.96257 2.43262C5.71556 0.91688 8.0007 0 10.5 0C16.0228 0 20.5 4.47715 20.5 10C20.5 12.1361 19.8302 14.1158 18.6892 15.7406L15.5 10H18.5C18.5 5.58172 14.9183 2 10.5 2C8.34982 2 6.39777 2.84827 4.96023 4.22842L3.96257 2.43262ZM17.0374 17.5674C15.2844 19.0831 12.9993 20 10.5 20C4.97715 20 0.5 15.5228 0.5 10C0.5 7.86386 1.16979 5.88416 2.3108 4.25944L5.5 10H2.5C2.5 14.4183 6.08172 18 10.5 18C12.6502 18 14.6022 17.1517 16.0398 15.7716L17.0374 17.5674Z" fill="currentColor"/>
+</svg>

+ 57 - 21
src/views/exercise_questions/preview/ChinesePreview.vue

@@ -6,27 +6,39 @@
       <span v-html="sanitizeHTML(data.stem)"></span>
     </div>
     <div v-if="isEnable(data.property.is_enable_description)" class="description">{{ data.description }}</div>
-    <template v-if="data.property.learn_type === 'paint'">
-      <!-- 描红 -->
-    </template>
-    <template v-else-if="data.property.learn_type === 'write'">
-      <!-- 书写 -->
-    </template>
-    <template v-else>
-      <!-- 笔画学习 -->
-    </template>
+
+    <!-- 笔画学习 -->
     <div class="words-box">
       <div v-for="(item, index) in data.option_list" :key="index" class="words-item">
-        <div class="words-info">
-          <AudioPlay :file-id="item.audio_file_id" theme-color="gray" />
-          <span class="pinyin">{{ item.pinyin }}</span>
-        </div>
-        <Strockplayredline
-          :play-storkes="true"
-          :book-text="item.content"
-          :target-div="'pra' + item.content + index"
-          class="strock-chinese"
-        />
+        <template v-if="item.content.trim()">
+          <template v-if="data.property.learn_type === 'paint'">
+            <!-- 描红 -->
+            <Strockred
+              :book-text="item.content"
+              :hanzi-color="hanzi_color"
+              :reset="true"
+              :target-div="'write-praT' + item.content"
+              :book-strokes="item.strokes"
+              class="strock-chinese"
+            />
+          </template>
+          <template v-else-if="data.property.learn_type === 'write'">
+            <!-- 书写 -->
+          </template>
+          <template v-else>
+            <div class="words-info">
+              <AudioPlay :file-id="item.audio_file_id" theme-color="gray" />
+              <span class="pinyin">{{ item.pinyin }}</span>
+            </div>
+            <Strockplayredline
+              :play-storkes="true"
+              :book-text="item.content"
+              :target-div="'pra' + item.content + index"
+              :book-strokes="item.strokes"
+              class="strock-chinese"
+            />
+          </template>
+        </template>
       </div>
     </div>
   </div>
@@ -35,20 +47,44 @@
 <script>
 import PreviewMixin from './components/PreviewMixin';
 import Strockplayredline from './components/common/Strockplayredline.vue';
+import Strockred from './components/common/Strockred.vue';
+import { GetStaticResources } from '@/api/exercise';
 
 export default {
   name: 'ChinesePreview',
   components: {
     Strockplayredline,
+    Strockred,
   },
   mixins: [PreviewMixin],
   data() {
-    return {};
+    return {
+      hanzi_color: '#404040', // 描红汉字底色
+      writer_number: 19, // 书写个数
+    };
   },
   created() {
     console.log(this.data);
+    this.handleData();
+  },
+  methods: {
+    // 初始化数据
+    handleData() {
+      // console.log(document.getElementsByClassName('preview-content')[0].clientWidth);
+
+      this.data.option_list.forEach((item) => {
+        if (item.content.trim()) {
+          let MethodName = 'hz_resource_manager-GetHZStrokesContent';
+          let data = {
+            hz: item.content.trim(),
+          };
+          GetStaticResources(MethodName, data).then((res) => {
+            this.$set(item, 'strokes', res);
+          });
+        }
+      });
+    },
   },
-  methods: {},
 };
 </script>
 

+ 1 - 1
src/views/exercise_questions/preview/ChooseTonePreview.vue

@@ -106,7 +106,7 @@ export default {
   },
   methods: {
     chooseTone(item, value, i) {
-      if (this.select_item_index !== i) return;
+      if (this.select_item_index !== i && this.data.property.answer_mode === 'label') return;
       if (!this.active_letter && this.data.property.answer_mode === 'label') return;
       item.user_answer[item.item_active_index].select_tone = value;
       if (this.data.property.answer_mode === 'label') {

+ 5 - 11
src/views/exercise_questions/preview/components/common/Strockplayredline.vue

@@ -12,11 +12,9 @@
 </template>
 
 <script>
-import { GetStaticResources } from '@/api/exercise';
 const HanziWriter = require('hanzi-writer');
 export default {
   components: {},
-  // props: ['targetDiv', 'BookText', 'playStorkes', 'strokeColor', 'themeColor'],
   props: {
     bookText: {
       type: String,
@@ -34,6 +32,10 @@ export default {
       type: String,
       default: '',
     },
+    bookStrokes: {
+      type: Object,
+      default: () => {},
+    },
   },
   data() {
     return {
@@ -75,17 +77,9 @@ export default {
   methods: {
     initHanziwrite() {
       let _this = this;
-      // _this.writer = null;
       _this.writer = HanziWriter.default.create(_this.targetDiv, _this.bookText, {
         charDataLoader(char, onComplete) {
-          console.log(_this.bookText);
-          let MethodName = 'hz_resource_manager-GetHZStrokesContent';
-          let data = {
-            hz: char,
-          };
-          GetStaticResources(MethodName, data).then((res) => {
-            onComplete(res);
-          });
+          onComplete(_this.bookStrokes);
         },
         padding: 5,
         showOutline: true,

+ 169 - 0
src/views/exercise_questions/preview/components/common/Strockred.vue

@@ -0,0 +1,169 @@
+<!--  -->
+<template>
+  <div class="strockredBox">
+    <div class="strockred">
+      <div class="character-target-box">
+        <SvgIcon icon-class="hanzi-writer-bg" class="character-target-bg" />
+        <div :id="targetDiv" class="character-target-div"></div>
+      </div>
+      <div v-if="reset" :class="['reset-box']" @click="resetHanzi">
+        <SvgIcon icon-class="reset" class="reset-btn" />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+const HanziWriter = require('hanzi-writer');
+export default {
+  name: 'Strockred',
+  components: {},
+  props: {
+    bookText: {
+      type: String,
+      default: '',
+    },
+    targetDiv: {
+      type: String,
+      default: '',
+    },
+    reset: {
+      type: Boolean,
+      default: true,
+    },
+    hanziColor: {
+      type: String,
+      default: '',
+    },
+    bookStrokes: {
+      type: Object,
+      default: () => {},
+    },
+  },
+  data() {
+    return {
+      writer: null,
+    };
+  },
+  computed: {},
+  watch: {
+    hanziColor(newVal, oldVal) {
+      this.updateColor(newVal);
+    },
+    Book_text: {
+      handler(val, oldVal) {
+        if (val !== oldVal) {
+          let _this = this;
+          _this.$nextTick(() => {
+            _this.initHanziwrite();
+          });
+        }
+      },
+      // 深度观察监听
+      deep: true,
+    },
+  },
+  // 生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  // 生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {
+    let _this = this;
+    _this.$nextTick(() => {
+      _this.initHanziwrite();
+    });
+  },
+  beforeCreate() {}, // 生命周期 - 创建之前
+  beforeMount() {}, // 生命周期 - 挂载之前
+  beforeUpdate() {}, // 生命周期 - 更新之前
+  updated() {}, // 生命周期 - 更新之后
+  beforeDestroy() {}, // 生命周期 - 销毁之前
+  destroyed() {}, // 生命周期 - 销毁完成
+  activated() {},
+  // 方法集合
+  methods: {
+    initHanziwrite() {
+      let _this = this;
+      let options = {
+        charDataLoader(char, onComplete) {
+          onComplete(_this.bookStrokes);
+        },
+        padding: 5,
+        showCharacter: false,
+        strokeColor: _this.hanziColor,
+        drawingColor: _this.hanziColor,
+        drawingWidth: 6,
+      };
+      _this.writer = HanziWriter.default.create(_this.targetDiv, _this.Book_text, options);
+      _this.writer.quiz();
+    },
+    resetHanzi() {
+      let _this = this;
+      _this.writer.quiz();
+    },
+    updateColor(color) {
+      let _this = this;
+      _this.writer.updateColor('strokeColor', color);
+      _this.writer.updateColor('drawingColor', color);
+    },
+  }, // 如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang="scss" scoped>
+//@import url(); 引入公共css类
+.strockredBox {
+  width: 64px; //444px
+  height: 64px; //480px
+}
+
+.strockred {
+  position: relative;
+  width: 100%;
+  height: 100%;
+  margin: 0 auto;
+
+  .character-target-div {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 99;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 100%;
+    height: 100%;
+  }
+
+  .character-target-box {
+    position: relative;
+    width: 100%;
+    height: 100%;
+  }
+
+  .character-target-bg {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    color: #dedede;
+  }
+
+  .reset-box {
+    position: absolute;
+    right: 2px;
+    bottom: 2px;
+    z-index: 100;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 11px;
+    height: 11px;
+    color: $text-color;
+    cursor: pointer;
+
+    &:hover {
+      color: #000;
+    }
+  }
+}
+</style>