Explorar o código

Merge branch 'lhd'

natasha hai 1 semana
pai
achega
7030d537b6

+ 2 - 1
src/views/book/courseware/create/components/base/common/UploadFile.vue

@@ -295,7 +295,8 @@ export default {
         this.type === 'image_text' ||
         this.type === 'drawing' ||
         this.type === 'character_structure' ||
-        this.type === 'newWord_template'
+        this.type === 'newWord_template' ||
+        this.type === 'character'
       ) {
         fileType = ['jpg', 'png', 'jpeg'];
         typeTip = '图片文件只能是 jpg、png、jpeg 格式!';

+ 285 - 112
src/views/book/courseware/create/components/question/character/Character.vue

@@ -3,63 +3,115 @@
     <template #content>
       <!-- eslint-disable max-len -->
       <div class="character-wrapper">
-        <el-input
-          v-model="data.content"
-          placeholder="输入"
-          type="textarea"
-          maxlength="10"
-          show-word-limit
-          @change="handleChangeContent"
-        />
-        <span class="tips">输入字或词请一字一行</span>
-        <template v-if="data.content_list.length > 0">
-          <el-divider content-position="left">拼音效果</el-divider>
-          <div class="content-list">
-            <div
-              v-for="(item, index) in data.content_list"
-              :key="index"
-              title="点击校对拼音"
-              @click="correctPinyin1(item.con, index)"
-            >
-              <span>{{ item.pinyin }}</span>
-              <b>{{ item.con }}</b>
-            </div>
+        <div class="fun-type">
+          <a
+            v-for="{ value, label } in modelList"
+            :key="value"
+            :class="[data.property.model === value ? 'active' : '']"
+            @click="data.property.model = value"
+            >{{ label }}</a
+          >
+        </div>
+        <div class="content-box" v-for="(item, index) in data.option_list" :key="index">
+          <div class="content-item">
+            <el-input
+              v-model="item.content"
+              maxlength="10"
+              show-word-limit
+              placeholder="输入汉字,@:代表图片,#:代表书写格"
+              @blur="handleMindMap"
+            ></el-input>
+            <el-button @click="identify(item, index)">识别</el-button>
+            <el-button @click="handleDelete(index)">删除此条</el-button>
           </div>
-        </template>
+          <div class="option-item">
+            <template v-if="data.property.model === 'miao'">
+              <span>显示本体:</span>
+              <el-radio-group v-model="item.is_show_ben">
+                <el-radio :label="true">是</el-radio>
+                <el-radio :label="false">否</el-radio>
+              </el-radio-group>
+            </template>
+            <template v-if="data.property.model === 'write'">
+              <span>需要间距:</span>
+              <el-radio-group v-model="item.is_margin">
+                <el-radio :label="true">是</el-radio>
+                <el-radio :label="false">否</el-radio>
+              </el-radio-group>
+            </template>
+            <template v-if="isEnable(data.property.is_enable_pinyin)">
+              <span>共用拼音:</span>
+              <el-radio-group v-model="item.is_common_pinyin">
+                <el-radio :label="true">是</el-radio>
+                <el-radio :label="false">否</el-radio>
+              </el-radio-group>
+              <template v-if="item.is_common_pinyin">
+                <span>拼音</span>
+                <el-input v-model="item.pinyin" placeholder="输入拼音"></el-input>
+              </template>
+            </template>
+
+            <template v-if="isEnable(data.property.is_enable_shiyi)">
+              <span>释义</span>
+              <el-input v-model="item.shiyi" placeholder="输入释义"></el-input>
+            </template>
+          </div>
+          <div class="content-items" v-for="(items, indexs) in item.content_list" :key="indexs">
+            <template v-if="items">
+              <label>内容:{{ items.con }} </label>
+              <UploadFile
+                v-if="items.type === 'img'"
+                :type="data.type"
+                :file-list="items.file_list"
+                :file-id-list="items.file_id_list"
+                :label-text="'图片'"
+                :accept-file-type="acceptFileType"
+                :index="index"
+                :indexs="indexs"
+                :limit="1"
+                @updateFileList="updateFileList"
+              />
+              <div class="option-item">
+                <template v-if="isEnable(data.property.is_enable_pinyin) && !item.is_common_pinyin">
+                  <span>拼音</span>
+                  <el-input v-model="items.pinyin" placeholder="输入拼音"></el-input>
+                </template>
+                <!-- <template v-if="isEnable(data.property.is_enable_shiyi) && data.property.model === 'input'">
+                <span>释义</span>
+                <el-input v-model="items.shiyi" placeholder="输入释义"></el-input>
+              </template> -->
+              </div>
+            </template>
+          </div>
+        </div>
+        <el-button icon="el-icon-plus" style="margin: 10px 0" @click="addElement">增加一个</el-button>
       </div>
-      <CorrectPinyin :visible.sync="visible" :select-content="selectContent" @fillTonePinyin="fillTonePinyin" />
     </template>
   </ModuleBase>
 </template>
 
 <script>
 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 { getCharacterData } from '@/views/book/courseware/data/character';
+import { getCharacterData, modelList, getOption } from '@/views/book/courseware/data/character';
 import { GetStaticResources } from '@/api/app';
 import cnchar from 'cnchar';
-import CorrectPinyin from '@/views/book/courseware/create/components/base/common/CorrectPinyin.vue';
+import UploadFile from '../../base/common/UploadFile.vue';
 
 export default {
   name: 'CharacterPage',
-  components: {
-    SoundRecord,
-    UploadAudio,
-    CorrectPinyin,
-  },
+  components: { UploadFile },
   mixins: [ModuleMixin],
   data() {
     return {
       data: getCharacterData(),
-      visible: false,
-      selectContent: '',
-      paragraph_index: 0,
+      modelList,
+      getOption,
+      acceptFileType: '.png,.jpg,.jpeg',
     };
   },
   watch: {
-    'data.content': 'handleMindMap',
+    // 'data.content': 'handleMindMap',
   },
   methods: {
     // 解析输入内容
@@ -113,45 +165,123 @@ export default {
       })
         .then(({ status, file_id }) => {
           if (status === 1) {
-            this.data.content_list[index].audio_file_id = file_id;
+            this.data.option_list[index].audio_file_id = file_id;
           }
         })
         .catch(() => {});
     },
-    // 校对拼音
-    correctPinyin1(text, i) {
-      if (text) {
-        this.visible = true;
-        this.selectContent = text;
-        this.paragraph_index = i;
-      }
+    updateFileList({ file_list, file_id_list }, index, indexs) {
+      this.data.option_list[index].content_list[indexs].file_list = file_list;
+      this.data.option_list[index].content_list[indexs].file_id_list = file_id_list;
     },
-    // 回填校对后的拼音
-    fillTonePinyin(tonePinyin) {
-      this.data.content_list[this.paragraph_index].pinyin = tonePinyin;
-      let MethodName = 'tool-PinyinToVoiceFile';
-      let data = {
-        pinyin: tonePinyin.split(' ').join(','),
-      };
-      GetStaticResources(MethodName, data)
-        .then((res) => {
-          if (res.status === 1) {
-            this.data.content_list[this.paragraph_index].audio_file_id = res.file_id;
-          }
-        })
-        .catch(() => {});
+    // 增加
+    addElement() {
+      this.data.option_list.push(getOption());
+    },
+    // 删除
+    handleDelete(index) {
+      this.data.option_list.splice(index, 1);
     },
     handleMindMap() {
       // 思维导图数据
       let node_list = [];
-      this.data.content_list.forEach((item) => {
+      this.data.option_list.forEach((item) => {
         node_list.push({
-          name: item.con,
+          name: item.content.replace(/<[^>]*>?/gm, ''),
           id: Math.random().toString(36).substring(2, 12),
         });
       });
       this.data.mind_map.node_list = node_list;
     },
+    // 识别
+    async identify(items, index) {
+      let con = items.content.trim();
+      if (con) {
+        items.content_list = [];
+        let arr = con.split('');
+        const regex = /[\u4E00-\u9FFF]/;
+        let str = '';
+        arr.forEach((item) => {
+          if (regex.test(item)) {
+            str += item;
+          }
+        });
+        let MethodName = 'hz_resource_manager-GetMultHZStrokesContent';
+        let data = {
+          hz_str: str,
+        };
+        items.pinyin = cnchar.spell(str, 'array', 'low', 'tone').join(' ');
+        await GetStaticResources(MethodName, data)
+          .then((res) => {
+            for (let key in res) {
+              if (key != 'status' && key != ',' && res[key]) {
+                res[key] = JSON.parse(res[key]);
+              }
+            }
+            let hzDetailList = res;
+            arr.forEach((item, index) => {
+              let objs = {};
+              if (item === '@') {
+                // 图片
+                objs = {
+                  con: item,
+                  type: 'img',
+                  file_list: [],
+                  file_id_list: [],
+                  pinyin: '',
+                };
+              } else if (item === '#') {
+                // 书写
+                objs = {
+                  con: item,
+                  type: 'write',
+                  img: '',
+                  base64: '',
+                  pinyin: '',
+                };
+              } else if (regex.test(item)) {
+                // 汉字
+                let hz_list = [];
+                let res = JSON.parse(JSON.stringify(hzDetailList[item]));
+                let obj = {
+                  con: item,
+                  hzDetail: {
+                    hz_json: res,
+                  },
+                };
+                hz_list.push(obj);
+                objs = {
+                  con: item,
+                  type: 'hanzi',
+                  hz_info: hz_list,
+                  pinyin: cnchar.spell(item, 'array', 'low', 'tone').join(' '),
+                  shiyi: '',
+                  answer: '',
+                  is_example: false,
+                  answer_pinyin: '',
+                  answer_en: '',
+                  is_can_input_answer: true,
+                  high_strokes: '',
+                };
+              } else {
+                // 连字符
+                objs = {
+                  con: item,
+                  type: 'lian',
+                  pinyin: '',
+                };
+              }
+              this.$set(items.content_list, index, objs);
+            });
+          })
+          .catch(() => {});
+        if (str) {
+          this.handleMatic(str, index);
+        }
+      } else {
+        this.$message.warning('请先输入内容');
+      }
+    },
   },
 };
 </script>
@@ -172,84 +302,127 @@ export default {
     color: #999;
   }
 
-  .content-list {
+  .fun-type {
     display: flex;
-    flex-wrap: wrap;
-    gap: 8px 8px;
+    gap: 5px;
+    width: 100%;
+    padding-bottom: 10px;
+    border-bottom: 1px solid #e5e6eb;
 
-    div {
-      text-align: center;
+    a {
+      padding: 5px 10px;
+      font-weight: normal;
+      color: #1d2129;
       cursor: pointer;
+      background: #f2f3f5;
+      border: 1px solid #f2f3f5;
+      border-radius: 2px;
 
-      span {
-        font-family: 'League';
-      }
-
-      b {
-        display: block;
-        font-family: '楷体';
-        font-weight: normal;
+      &.active {
+        color: #165dff;
+        background: #e7eeff;
+        border-color: #165dff;
       }
     }
   }
 
-  .auto-matic,
-  .upload-audio-play {
-    :deep .upload-wrapper {
-      margin-top: 0;
-    }
+  .upload-file {
+    display: flex;
+    column-gap: 12px;
+    align-items: center;
+    margin: 8px 0;
 
-    .audio-wrapper {
-      :deep .audio-play {
-        width: 16px;
-        height: 16px;
-        color: #000;
-        background-color: initial;
-      }
+    .file-name {
+      display: flex;
+      column-gap: 14px;
+      align-items: center;
+      justify-content: space-between;
+      max-width: 360px;
+      padding: 8px 12px;
+      font-size: 14px;
+      color: #1d2129;
+      background-color: #f7f8fa;
 
-      :deep .audio-play.not-url {
-        color: #a1a1a1;
+      span {
+        display: flex;
+        column-gap: 14px;
+        align-items: center;
       }
+    }
 
-      :deep .voice-play {
-        width: 16px;
-        height: 16px;
-      }
+    .svg-icon {
+      cursor: pointer;
     }
   }
 
-  .auto-matic {
+  .fun-type {
     display: flex;
-    flex-shrink: 0;
-    column-gap: 12px;
-    align-items: center;
-    width: 200px;
-    padding: 5px 12px;
-    background-color: $fill-color;
-    border-radius: 2px;
+    gap: 5px;
+    width: 100%;
+    padding-bottom: 10px;
+    border-bottom: 1px solid #e5e6eb;
 
-    .auto-btn {
-      font-size: 16px;
-      font-weight: 400;
-      line-height: 22px;
+    a {
+      padding: 5px 10px;
+      font-weight: normal;
       color: #1d2129;
       cursor: pointer;
+      background: #f2f3f5;
+      border: 1px solid #f2f3f5;
+      border-radius: 2px;
+
+      &.active {
+        color: #165dff;
+        background: #e7eeff;
+        border-color: #165dff;
+      }
+    }
+  }
+
+  .content-box {
+    width: 100%;
+  }
+
+  .content-item {
+    display: flex;
+    gap: 16px;
+
+    .el-input {
+      max-width: 400px;
+    }
+  }
+
+  .content-items {
+    margin: 10px 0;
+
+    label {
+      font-size: 14px;
+      line-height: 34px;
+      color: #4e5969;
     }
   }
 
-  .correct-answer {
+  .option-item {
     display: flex;
-    flex-wrap: wrap;
-    gap: 8px;
+    flex-flow: wrap;
+    align-items: center;
+    margin-top: 5px;
+
+    span {
+      flex-shrink: 0;
+      width: max-content;
+      margin-right: 10px;
+      font-size: 14px;
+      color: #4e5969;
+    }
 
     .el-input {
-      width: 180px;
+      max-width: 100px;
+      margin-right: 30px;
+    }
 
-      :deep &__prefix {
-        display: flex;
-        align-items: center;
-        color: $text-color;
-      }
+    .el-radio-group {
+      margin-right: 30px;
     }
   }
 }

+ 30 - 2
src/views/book/courseware/create/components/question/character/CharacterSetting.vue

@@ -14,6 +14,27 @@
       </el-form-item>
 
       <el-divider />
+      <el-form-item v-if="property.model === 'miao'" label="描红格">
+        <el-input-number v-model="property.miao_number" :min="0" :step="1" />
+      </el-form-item>
+      <el-form-item label="书写格" v-if="property.model === 'miao'">
+        <el-input-number v-model="property.write_number" :min="0" :step="1" />
+      </el-form-item>
+      <el-divider v-if="property.model === 'miao'" />
+      <el-form-item label="错误提示" v-if="property.model === 'miao'">
+        <el-radio-group v-model="property.is_enable_error">
+          <el-radio v-for="{ value, label } in showList" :key="value" :label="value">
+            {{ label }}
+          </el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="笔迹回放">
+        <el-radio-group v-model="property.is_enable_play_back">
+          <el-radio v-for="{ value, label } in showList" :key="value" :label="value">
+            {{ label }}
+          </el-radio>
+        </el-radio-group>
+      </el-form-item>
       <el-form-item label="笔画动画">
         <el-radio-group v-model="property.is_enable_stroke">
           <el-radio v-for="{ value, label } in showList" :key="value" :label="value">
@@ -21,14 +42,21 @@
           </el-radio>
         </el-radio-group>
       </el-form-item>
-      <el-form-item label="拼音显示">
+      <el-form-item label="拼音">
         <el-radio-group v-model="property.is_enable_pinyin">
           <el-radio v-for="{ value, label } in showList" :key="value" :label="value">
             {{ label }}
           </el-radio>
         </el-radio-group>
       </el-form-item>
-      <el-form-item label="读音显示">
+      <el-form-item label="释义">
+        <el-radio-group v-model="property.is_enable_shiyi">
+          <el-radio v-for="{ value, label } in showList" :key="value" :label="value">
+            {{ label }}
+          </el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="读音">
         <el-radio-group v-model="property.is_enable_voice">
           <el-radio v-for="{ value, label } in showList" :key="value" :label="value">
             {{ label }}

+ 36 - 28
src/views/book/courseware/create/components/question/newWord_template/NewWordTemplate.vue

@@ -28,14 +28,17 @@
             @blur="handleMindMap"
           ></el-input>
           <el-button @click="identify(item)">识别</el-button>
+          <el-button @click="handleDelete(index)">删除</el-button>
         </div>
         <div class="option-item">
-          <template v-if="isEnable(data.property.is_enable_pinyin) || data.answer_type.indexOf('pinyin') > -1">
-            <span>共用拼音:</span>
-            <el-radio-group v-model="item.is_common_pinyin">
-              <el-radio :label="true">是</el-radio>
-              <el-radio :label="false">否</el-radio>
-            </el-radio-group>
+          <template v-if="data.property.model === 'input'">
+            <template v-if="isEnable(data.property.is_enable_pinyin)">
+              <span>共用拼音:</span>
+              <el-radio-group v-model="item.is_common_pinyin">
+                <el-radio :label="true">是</el-radio>
+                <el-radio :label="false">否</el-radio>
+              </el-radio-group>
+            </template>
             <template
               v-if="
                 isEnable(data.property.is_enable_pinyin) && data.property.model === 'input' && item.is_common_pinyin
@@ -50,28 +53,27 @@
               <span>拼音答案</span>
               <el-input v-model="item.answer_pinyin" placeholder="输入拼音"></el-input>
             </template>
-
-            <template v-if="isEnable(data.property.is_enable_shiyi) && data.property.model === 'input'">
-              <span>释义</span>
-              <el-input v-model="item.shiyi" placeholder="输入释义"></el-input>
-            </template>
-            <template v-if="data.answer_type.indexOf('en') > -1 && data.property.model === 'input'">
-              <span>释义答案</span>
-              <el-input v-model="item.answer_en" placeholder="输入释义"></el-input>
-            </template>
-            <template
-              v-if="
-                data.property.model === 'input' &&
-                (data.answer_type.indexOf('en') > -1 ||
-                  (data.answer_type.indexOf('pinyin') > -1 && item.is_common_pinyin))
-              "
-            >
-              <span>例子</span>
-              <el-radio-group v-model="item.is_example">
-                <el-radio :label="true">是</el-radio>
-                <el-radio :label="false">否</el-radio>
-              </el-radio-group>
-            </template>
+          </template>
+          <template v-if="isEnable(data.property.is_enable_shiyi) && data.property.model === 'input'">
+            <span>释义</span>
+            <el-input v-model="item.shiyi" placeholder="输入释义"></el-input>
+          </template>
+          <template v-if="data.answer_type.indexOf('en') > -1 && data.property.model === 'input'">
+            <span>释义答案</span>
+            <el-input v-model="item.answer_en" placeholder="输入释义"></el-input>
+          </template>
+          <template
+            v-if="
+              data.property.model === 'input' &&
+              (data.answer_type.indexOf('en') > -1 ||
+                (data.answer_type.indexOf('pinyin') > -1 && item.is_common_pinyin))
+            "
+          >
+            <span>例子</span>
+            <el-radio-group v-model="item.is_example">
+              <el-radio :label="true">是</el-radio>
+              <el-radio :label="false">否</el-radio>
+            </el-radio-group>
           </template>
         </div>
         <div class="content-items" v-for="(items, indexs) in item.content_list" :key="indexs">
@@ -176,6 +178,7 @@ export default {
       answer_list,
       getOption,
       acceptFileType: '.png,.jpg,.jpeg',
+      isEnable,
     };
   },
   watch: {
@@ -190,6 +193,10 @@ export default {
     addElement() {
       this.data.option_list.push(getOption());
     },
+    // 删除
+    handleDelete(index) {
+      this.data.option_list.splice(index, 1);
+    },
     handleMindMap() {
       // 思维导图数据
       let node_list = [];
@@ -214,6 +221,7 @@ export default {
             str += item;
           }
         });
+        items.pinyin = cnchar.spell(str, 'array', 'low', 'tone').join(' ');
         let MethodName = 'hz_resource_manager-GetMultHZStrokesContent';
         let data = {
           hz_str: str,

+ 1 - 1
src/views/book/courseware/create/components/question/newWord_template/NewWordTemplateSetting.vue

@@ -2,7 +2,7 @@
   <div>
     <el-form :model="property" label-width="72px" label-position="left">
       <SerailNumber :property="property" />
-      <el-form-item label="播放笔顺">
+      <el-form-item label="笔画动画">
         <el-radio-group v-model="property.is_enable_play_structure">
           <el-radio v-for="{ value, label } in showList" :key="value" :label="value">
             {{ label }}

+ 37 - 2
src/views/book/courseware/data/character.js

@@ -6,8 +6,21 @@ import {
   switchOption,
   isEnable,
 } from '@/views/book/courseware/data/common';
+import { getRandomNumber } from '@/utils';
 
 export { arrangeTypeList, switchOption, isEnable };
+  
+// 模式类型
+export const modelList = [
+  {
+    value: 'miao',
+    label: '汉字展示及书写',
+  },
+  {
+    value: 'write',
+    label: '汉字书写',
+  },
+];
 
 // 显示
 export const showList = [
@@ -36,6 +49,22 @@ export const frameList = [
     label: '无',
   },
 ];
+export function getOption() {
+  return {
+    content: '',
+    pinyin: '',
+    shiyi:'',
+    mark: getRandomNumber(),
+    hz_info: [],
+    file_list: [],
+    file_id_list: [],
+    content_list: [],
+    is_common_pinyin: false,
+    audio_file_id: '',
+    is_margin: false,
+    is_show_ben: true,
+  };
+}
 
 export function getCharacterProperty() {
   return {
@@ -49,6 +78,13 @@ export function getCharacterProperty() {
     frame_color: '#F13232',
     is_enable_stroke: showList[0].value,
     is_enable_voice: showList[0].value,
+
+    model: modelList[0].value,
+    is_enable_shiyi: showList[0].value,
+    miao_number: 5,
+    write_number: 5,
+    is_enable_play_back: showList[0].value,
+    is_enable_error: showList[0].value,
   };
 }
 
@@ -57,8 +93,7 @@ export function getCharacterData() {
     type: 'character',
     title: '汉字',
     property: getCharacterProperty(),
-    content: '',
-    content_list: [],
+    option_list: [getOption()],
     mind_map: {
       node_list: [{ name: '汉字' }], // 思维导图数据
     },

+ 1 - 1
src/views/book/courseware/preview/components/dialogue_article/index.vue

@@ -180,7 +180,7 @@ export default {
     // NewWordPreview,
   },
   mixins: [PreviewMixin],
-  inject: ['bookInfo', 'courseware_id'],
+  inject: ['bookInfo'],
   watch: {
     'data.content': {
       handler(val) {

+ 11 - 3
src/views/book/courseware/preview/components/newWord_template/NewWordTemplatePreview.vue

@@ -48,8 +48,15 @@
               v-for="(items, indexs) in item.content_list"
               :key="indexs"
             >
-              {{ items.high_strokes }}
-              <div v-if="isEnable(data.property.is_enable_pinyin)" class="pinyin">{{ items.pinyin }}</div>
+              <div
+                v-if="
+                  isEnable(data.property.is_enable_pinyin) &&
+                  (data.property.model === 'miao' || (data.property.model === 'input' && !item.is_common_pinyin))
+                "
+                class="pinyin"
+              >
+                {{ items.pinyin }}
+              </div>
               <div
                 class="inputdv pinyin-common"
                 v-if="
@@ -337,7 +344,8 @@ export default {
 
   .en-common {
     margin-top: 8px;
-    text-align: center;
+
+    // text-align: center;
     word-break: break-word;
   }
 }