Jelajahi Sumber

替换练习

natasha 1 tahun lalu
induk
melakukan
1078003c80

+ 3 - 0
src/views/exercise_questions/create/components/create.vue

@@ -61,6 +61,7 @@ import ListenFillQuestion from './exercises/ListenFillQuestion.vue';
 import WordCardQuestion from './exercises/WordCardQuestion.vue';
 import AnswerQuestion from './exercises/AnswerQuestion.vue';
 import WritePictureQuestion from './exercises/WritePictureQuestion.vue';
+import ReplaceAnswerQuestion from './exercises/ReplaceAnswerQuestion.vue';
 
 export default {
   name: 'CreateMain',
@@ -85,6 +86,7 @@ export default {
     WordCardQuestion,
     AnswerQuestion,
     WritePictureQuestion,
+    ReplaceAnswerQuestion,
   },
   provide() {
     return {
@@ -127,6 +129,7 @@ export default {
         word_card: WordCardQuestion,
         answer_question: AnswerQuestion,
         write_picture: WritePictureQuestion,
+        replace_answer: ReplaceAnswerQuestion,
       },
     };
   },

+ 1 - 1
src/views/exercise_questions/create/components/exercises/AnswerQuestion.vue

@@ -109,7 +109,7 @@ import UploadAudio from '../common/UploadAudio.vue';
 import { answerQuestionData } from '@/views/exercise_questions/data/answerQuestion';
 
 export default {
-  name: 'ReadAloudQuestion',
+  name: 'AnswerQuestion',
   components: { UploadAudio },
   mixins: [QuestionMixin],
   data() {

+ 157 - 0
src/views/exercise_questions/create/components/exercises/ReplaceAnswerQuestion.vue

@@ -0,0 +1,157 @@
+<!-- 听读训练 -->
+<template>
+  <QuestionBase>
+    <template #content>
+      <div class="stem">
+        <el-input
+          v-if="data.property.stem_type === stemTypeList[0].value"
+          v-model="data.stem"
+          rows="3"
+          resize="none"
+          type="textarea"
+          placeholder="输入题干"
+        />
+
+        <RichText v-if="data.property.stem_type === stemTypeList[1].value" v-model="data.stem" placeholder="输入题干" />
+
+        <el-input
+          v-show="isEnable(data.property.is_enable_description)"
+          v-model="data.description"
+          rows="3"
+          resize="none"
+          type="textarea"
+          placeholder="输入描述"
+        />
+      </div>
+
+      <div class="content">
+        <ul>
+          <li v-for="(item, i) in data.option_list" :key="i" class="content-item repeat-option">
+            <div class="option-content" v-for="(items, indexs) in item" :key="indexs">
+              <el-input v-model="items.content" placeholder="输入内容"></el-input>
+            </div>
+          </li>
+        </ul>
+      </div>
+    </template>
+
+    <template #property>
+      <el-form :model="data.property">
+        <el-form-item label="题干">
+          <el-radio
+            v-for="{ value, label } in stemTypeList"
+            :key="value"
+            v-model="data.property.stem_type"
+            :label="value"
+          >
+            {{ label }}
+          </el-radio>
+        </el-form-item>
+        <el-form-item label="题号">
+          <el-input v-model="data.property.question_number" />
+        </el-form-item>
+        <el-form-item label-width="45px">
+          <el-radio
+            v-for="{ value, label } in questionNumberTypeList"
+            :key="value"
+            v-model="data.other.question_number_type"
+            :label="value"
+          >
+            {{ label }}
+          </el-radio>
+        </el-form-item>
+        <el-form-item label="描述">
+          <el-radio
+            v-for="{ value, label } in switchOption"
+            :key="value"
+            v-model="data.property.is_enable_description"
+            :label="value"
+          >
+            {{ label }}
+          </el-radio>
+        </el-form-item>
+        <el-form-item label="分值">
+          <el-radio
+            v-for="{ value, label } in scoreTypeList"
+            :key="value"
+            v-model="data.property.score_type"
+            :label="value"
+          >
+            {{ label }}
+          </el-radio>
+        </el-form-item>
+        <el-form-item label-width="45px">
+          <el-input-number
+            v-model="data.property.score"
+            :min="0"
+            :step="data.property.score_type === scoreTypeList[0].value ? 1 : 0.1"
+          />
+        </el-form-item>
+        <el-form-item label="行数">
+          <el-input-number
+            :min="1"
+            :step="1"
+            v-model="data.property.rows_number"
+            class="word-num-input"
+            :precision="0"
+          />
+        </el-form-item>
+      </el-form>
+    </template>
+  </QuestionBase>
+</template>
+
+<script>
+import QuestionMixin from '../common/QuestionMixin.js';
+
+import { selectTypeList, changeOptionType } from '@/views/exercise_questions/data/common';
+import { replaceAnswerData, getOption } from '@/views/exercise_questions/data/replaceAnswer';
+
+export default {
+  name: 'ReplaceAnswertQuestion',
+  components: {},
+  mixins: [QuestionMixin],
+  data() {
+    return {
+      selectTypeList,
+      changeOptionType,
+      data: JSON.parse(JSON.stringify(replaceAnswerData)),
+    };
+  },
+  methods: {
+    /**
+     * 智能识别
+     * @param {String} text 识别数据
+     */
+    recognition(text) {
+      let arr = text
+        .split(/[\r\n]/)
+        .map((item) => item.trim())
+        .filter((item) => item);
+
+      if (arr.length > 0) {
+        this.data.stem = arr[0];
+        this.data.option_list = arr.slice(1).map((content) => getOption(content));
+      }
+    },
+    addOption() {
+      this.data.option_list.push(getOption());
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.repeat-option {
+  :deep .upload-wrapper {
+    margin-top: 0;
+  }
+
+  :deep .file-name {
+    width: 205px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+}
+</style>

+ 1 - 1
src/views/exercise_questions/create/components/exercises/WritePictureQuestion.vue

@@ -145,7 +145,7 @@ import { GetFileStoreInfo } from '@/api/app';
 import UploadDrag from '../common/UploadDrag.vue';
 
 export default {
-  name: 'TalkPicture',
+  name: 'WritePictureQuestion',
   mixins: [QuestionMixin],
   components: { UploadDrag },
   data() {

+ 3 - 0
src/views/exercise_questions/create/index.vue

@@ -89,6 +89,7 @@ import ListenJudgePreview from '../preview/ListenJudgePreview.vue';
 import WordCardPreview from '../preview/WordCardPreview.vue';
 import AnswerQuestionPreview from '../preview/AnswerQuestionPreview.vue';
 import WritePictruePreview from '../preview/WritePictruePreview.vue';
+import ReplaceAnswerPreview from '../preview/ReplaceAnswerPreview.vue';
 
 export default {
   name: 'CreateExercise',
@@ -113,6 +114,7 @@ export default {
     WordCardPreview,
     AnswerQuestionPreview,
     WritePictruePreview,
+    ReplaceAnswerPreview,
   },
   provide() {
     return {
@@ -155,6 +157,7 @@ export default {
         word_card: WordCardPreview,
         answer_question: AnswerQuestionPreview,
         write_picture: WritePictruePreview,
+        replace_answer: ReplaceAnswerPreview,
       },
     };
   },

+ 1 - 0
src/views/exercise_questions/data/common.js

@@ -23,6 +23,7 @@ export const questionTypeOption = [
       { label: '看图说话', value: 'talk_picture' },
       { label: '对话题', value: 'dialogue' },
       { label: '回答问题', value: 'answer_question' },
+      { label: '替换练习', value: 'replace_answer' },
     ],
   },
   {

+ 33 - 0
src/views/exercise_questions/data/replaceAnswer.js

@@ -0,0 +1,33 @@
+import { stemTypeList, scoreTypeList, questionNumberTypeList } from './common';
+import { getRandomNumber } from '@/utils/index';
+
+export function getOption(content = '') {
+  return [
+    { content, mark: getRandomNumber() },
+    { content, mark: getRandomNumber() },
+    { content, mark: getRandomNumber() },
+    { content, mark: getRandomNumber() },
+  ];
+}
+
+// 听后训练数据模板
+export const replaceAnswerData = {
+  type: 'replace_answer', // 题型
+  stem: '', // 题干
+  description: '', // 描述
+  option_list: [getOption(), getOption(), getOption(), getOption()], // 选项
+  answer: { score: 0, score_type: scoreTypeList[0].value }, // 答案
+  // 题型属性
+  property: {
+    stem_type: stemTypeList[0].value, // 题干类型
+    question_number: '1', // 题号
+    is_enable_description: 'false', // 描述
+    score: 1, // 分值
+    score_type: scoreTypeList[0].value, // 分值类型
+    rows_number: 4,
+  },
+  // 其他属性
+  other: {
+    question_number_type: questionNumberTypeList[0].value, // 题号类型
+  },
+};

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

@@ -23,7 +23,7 @@ import PreviewMixin from './components/PreviewMixin';
 import SoundRecordPreview from './components/common/SoundRecordPreview.vue';
 
 export default {
-  name: 'ReadAloudPreview',
+  name: 'AnswerQuestionPreview',
   components: {
     SoundRecordPreview,
   },

+ 88 - 0
src/views/exercise_questions/preview/ReplaceAnswerPreview.vue

@@ -0,0 +1,88 @@
+<!-- eslint-disable vue/no-v-html -->
+<template>
+  <div class="repeat-preview">
+    <div class="stem">
+      <span class="question-number">{{ data.property.question_number }}.</span>
+      <span v-html="sanitizeHTML(data.stem)"></span>
+    </div>
+    <div v-if="isEnable(data.property.is_enable_description)" class="description">{{ data.description }}</div>
+    <div class="option-list">
+      <li v-for="(item, i) in answer_list" :key="i" :class="['option-item']"></li>
+    </div>
+  </div>
+</template>
+
+<script>
+import PreviewMixin from './components/PreviewMixin';
+import { computeOptionMethods } from '@/views/exercise_questions/data/common';
+import SoundRecordPreview from './components/common/SoundRecordPreview.vue';
+
+export default {
+  name: 'ReplaceAnswerPreview',
+  components: {
+    SoundRecordPreview,
+  },
+  mixins: [PreviewMixin],
+  data() {
+    return {
+      computeOptionMethods,
+      answer_list: [],
+    };
+  },
+  created() {
+    console.log(this.data);
+    this.handleData();
+  },
+  methods: {
+    // 初始化数据
+    handleData() {
+      this.answer_list = [];
+      this.data.option_list.forEach((item) => {
+        let obj = {
+          mark: item.mark,
+          audio_file_id: '',
+        };
+        this.answer_list.push(obj);
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+@use '@/styles/mixin.scss' as *;
+
+.repeat-preview {
+  @include preview;
+
+  .option-list {
+    // display: flex;
+    // flex-wrap: wrap;
+    // row-gap: 16px;
+
+    .option-item {
+      display: flex;
+      column-gap: 16px;
+      align-items: center;
+      width: 90%;
+      margin-bottom: 16px;
+
+      .option-content {
+        flex: 1;
+
+        // max-width: 306px;
+        padding: 8px 16px;
+        color: #706f78;
+        background-color: $content-color;
+        border-radius: 40px;
+      }
+
+      .sound-box {
+        padding: 4px;
+        background: $content-color;
+        border-radius: 40px;
+      }
+    }
+  }
+}
+</style>

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

@@ -76,7 +76,7 @@ import SoundRecordPreview from './components/common/SoundRecordPreview.vue';
 import UploadFiles from './components/common/UploadFiles.vue';
 
 export default {
-  name: 'TalkPictruePreview',
+  name: 'WritePicturePreview',
   components: {
     SoundRecordPreview,
     UploadFiles,