Переглянути джерело

Merge branch 'master' of http://60.205.254.193:3000/GCLS/GCLS_Page_Exercise

dusenyao 1 рік тому
батько
коміт
f2cea19b78

+ 77 - 7
src/views/exercise_questions/create/components/exercises/SortQuestion.vue

@@ -14,11 +14,37 @@
 
       <div class="content">
         <ul>
-          <li v-for="(item, i) in data.option_list" :key="i" class="content-item">
-            <div class="option-content">
-              <RichText v-model="item.content" placeholder="输入内容" :inline="true" />
+          <li
+            v-for="(item, i) in data.option_list"
+            :key="i"
+            class="content-item"
+            :class="['content-item-' + data.property.layout_type]"
+          >
+            <span
+              class="question-number"
+              title="双击切换序号类型"
+              @dblclick="changeOptionType(data)"
+              v-if="data.property.layout_type === 'horizontal'"
+            >
+              {{ computedQuestionNumber(i, data.option_number_show_mode) }}
+            </span>
+
+            <div class="option-content" v-for="(items, indexs) in item" :key="indexs">
+              <RichText v-model="items.content" placeholder="输入内容" :inline="true" />
+              <i class="el-icon-circle-close" @click="deleteOptionItem(i, indexs)"></i>
             </div>
-            <SvgIcon icon-class="delete" class="delete pointer" @click="deleteOption(i)" />
+            <SvgIcon
+              icon-class="add-circle"
+              size="16"
+              @click="addOptionItem(i)"
+              v-if="data.property.layout_type === 'horizontal'"
+            />
+            <SvgIcon
+              icon-class="delete"
+              class="delete pointer"
+              @click="deleteOption(i)"
+              v-if="data.property.layout_type === 'horizontal'"
+            />
           </li>
         </ul>
       </div>
@@ -61,6 +87,7 @@
             :key="value"
             v-model="data.property.layout_type"
             :label="value"
+            @change="changeType"
           >
             {{ label }}
           </el-radio>
@@ -92,6 +119,7 @@
 import QuestionMixin from '../common/QuestionMixin.js';
 
 import { getOption, sortTypeList, getSortDataTemplate } from '@/views/exercise_questions/data/sort';
+import { changeOptionType } from '@/views/exercise_questions/data/common';
 
 export default {
   name: 'SortQuestion',
@@ -99,6 +127,7 @@ export default {
   mixins: [QuestionMixin],
   data() {
     return {
+      changeOptionType,
       sortTypeList,
       data: getSortDataTemplate(),
     };
@@ -107,8 +136,11 @@ export default {
     'data.option_list': {
       handler(val) {
         if (!val) return;
-        this.data.answer.answer_list = val.map(({ mark }) => {
-          return mark;
+        this.data.answer.answer_list = val.map((item) => {
+          let answer_item = item.map((items) => {
+            return items.mark;
+          });
+          return answer_item;
         });
       },
       deep: true,
@@ -116,7 +148,14 @@ export default {
   },
   methods: {
     addOption() {
-      this.data.option_list.push(getOption());
+      if (this.data.property.layout_type === 'vertical') {
+        this.data.option_list[0].push(getOption());
+      } else {
+        this.data.option_list.push([getOption(), getOption(), getOption(), getOption(), getOption(), getOption()]);
+      }
+    },
+    addOptionItem(i) {
+      this.data.option_list[i].push(getOption());
     },
     /**
      * 智能识别
@@ -133,6 +172,37 @@ export default {
         this.data.option_list = arr.slice(1).map((content) => getOption(content));
       }
     },
+    changeType(item) {
+      if (item === 'vertical') {
+        this.data.option_list = this.data.option_list.splice(0, 1);
+      }
+    },
+    // 删除小题里的选项
+    deleteOptionItem(i, index) {
+      this.data.option_list[i].splice(index, 1);
+    },
   },
 };
 </script>
+<style lang="scss" scoped>
+.content-item {
+  flex-wrap: wrap;
+  row-gap: 4px;
+}
+
+.content-item-horizontal {
+  .option-content {
+    min-width: 110px;
+    max-width: 120px;
+  }
+}
+
+.question-container .question-content .content > ul .content-item-vertical {
+  display: block;
+
+  .option-content {
+    width: 100%;
+    margin-bottom: 4px;
+  }
+}
+</style>

+ 14 - 3
src/views/exercise_questions/data/sort.js

@@ -1,4 +1,4 @@
-import { stemTypeList, scoreTypeList, questionNumberTypeList, switchOption } from './common';
+import { stemTypeList, scoreTypeList, questionNumberTypeList, switchOption, optionTypeList } from './common';
 import { getRandomNumber } from '@/utils/index';
 
 export function getOption(content = '') {
@@ -10,8 +10,18 @@ export const sortTypeList = [
 ];
 // 选择题数据模板
 export function getSortDataTemplate() {
-  let option_list = [getOption(), getOption(), getOption()];
-  let answer_list = option_list.map(({ mark }) => mark);
+  let option_list = [
+    [getOption(), getOption(), getOption(), getOption(), getOption(), getOption()],
+    [getOption(), getOption(), getOption(), getOption(), getOption(), getOption()],
+    [getOption(), getOption(), getOption(), getOption(), getOption(), getOption()],
+  ];
+  let answer_list = option_list.map((item) => {
+    let answer_item = item.map((items) => {
+      return items.mark;
+    });
+    return answer_item;
+  });
+
   return {
     type: 'sort', // 题型
     stem: '', // 题干
@@ -19,6 +29,7 @@ export function getSortDataTemplate() {
     option_list, // 选项
     file_id_list: [], // 文件 id 列表
     answer: { answer_list, score: 1, score_type: scoreTypeList[0].value }, // 答案
+    option_number_show_mode: optionTypeList[0].value, // 选项类型
     // 题型属性
     property: {
       stem_type: stemTypeList[1].value, // 题干类型

+ 96 - 66
src/views/exercise_questions/preview/SortPreview.vue

@@ -10,69 +10,71 @@
       class="description rich-text"
       v-html="sanitizeHTML(data.description)"
     ></div>
-    <draggable
-      v-model="move_list"
-      animation="300"
-      :options="{
-        group: { name: 'itxst', pull: 'clone' },
-      }"
-      :sort="!disabled"
-      :class="['content-box', 'content-box-' + data.property.layout_type]"
-      @start="onStart($event)"
-      @end="onEnd($event)"
+    <div
+      v-for="(move_item, move_index) in move_list"
+      :key="move_index"
+      :class="['move-box-' + data.property.layout_type]"
     >
-      <transition-group>
-        <div
-          v-for="(itemNode, indexNode) in move_list"
-          :key="indexNode"
-          :class="[
-            'drag-item',
-            { error: itemNode.mark !== data.option_list[indexNode].mark && isJudgingRightWrong },
-            click_index_list.indexOf(indexNode) > -1 ? 'drag-item-active' : '',
-          ]"
-          @click="handleClickItem(indexNode)"
-        >
-          <!-- <SvgIcon
-            v-if="data.property.layout_type === 'vertical'"
-            class="drag-icon"
-            :size="20"
-            icon-class="draggable"
-          /> -->
-          <span class="drag-content rich-text" v-html="sanitizeHTML(itemNode.content)"></span>
-          <!-- <SvgIcon
-            v-if="data.property.layout_type === 'horizontal'"
-            class="drag-icon"
-            :size="20"
-            icon-class="draggable"
-          /> -->
-        </div>
-      </transition-group>
-    </draggable>
-    <template v-if="isShowRightAnswer && !is_all_right">
-      <h4 class="right-title">正确答案:</h4>
+      <span class="option-number" v-if="data.property.layout_type === 'horizontal'"
+        >{{ computeOptionMethods[data.option_number_show_mode](move_index) }}
+      </span>
       <draggable
-        v-model="move_list"
+        v-model="move_list[move_index]"
         animation="300"
         :options="{
           group: { name: 'itxst', pull: 'clone' },
         }"
-        :sort="false"
+        :sort="!disabled"
         :class="['content-box', 'content-box-' + data.property.layout_type]"
+        @start="onStart($event)"
+        @end="onEnd($event)"
+        :group="'move' + move_index"
       >
         <transition-group>
           <div
-            v-for="(itemNode, indexNode) in data.option_list"
+            v-for="(itemNode, indexNode) in move_item"
             :key="indexNode"
             :class="[
               'drag-item',
-              { error: itemNode.mark !== data.option_list[indexNode].mark && isJudgingRightWrong },
-              click_index_list.indexOf(indexNode) > -1 ? 'drag-item-active' : '',
+              { error: itemNode.mark !== data.option_list[move_index][indexNode].mark && isJudgingRightWrong },
+              click_index_list.indexOf(indexNode) > -1 && select_index === move_index ? 'drag-item-active' : '',
             ]"
+            @click="handleClickItem(move_index, indexNode)"
           >
             <span class="drag-content rich-text" v-html="sanitizeHTML(itemNode.content)"></span>
           </div>
         </transition-group>
       </draggable>
+    </div>
+    <template v-if="isShowRightAnswer && !is_all_right">
+      <h4 class="right-title">正确答案:</h4>
+
+      <template v-for="(move_item, move_index) in data.option_list">
+        <div
+          v-if="JSON.stringify(answer.answer_list[move_index]) !== JSON.stringify(data.answer.answer_list[move_index])"
+          :key="'answer' + move_index"
+          :class="['move-box-' + data.property.layout_type]"
+        >
+          <span class="option-number" v-if="data.property.layout_type === 'horizontal'"
+            >{{ computeOptionMethods[data.option_number_show_mode](move_index) }}
+          </span>
+          <draggable
+            v-model="move_list[move_index]"
+            animation="300"
+            :options="{
+              group: { name: 'itxst', pull: 'clone' },
+            }"
+            :sort="false"
+            :class="['content-box', 'content-box-' + data.property.layout_type]"
+          >
+            <transition-group>
+              <div v-for="(itemNode, indexNode) in move_item" :key="'answer-item' + indexNode" :class="['drag-item']">
+                <span class="drag-content rich-text" v-html="sanitizeHTML(itemNode.content)"></span>
+              </div>
+            </transition-group>
+          </draggable>
+        </div>
+      </template>
     </template>
   </div>
 </template>
@@ -80,6 +82,7 @@
 <script>
 import Draggable from 'vuedraggable';
 import PreviewMixin from './components/PreviewMixin';
+import { computeOptionMethods } from '@/views/exercise_questions/data/common';
 
 export default {
   name: 'SortPreview',
@@ -87,19 +90,24 @@ export default {
   mixins: [PreviewMixin],
   data() {
     return {
+      computeOptionMethods,
       move_list: [], // 移动后的数组
       drag: false,
       click_index_list: [], // 点击选中的索引
       disrupted: false, // 是否打乱
       is_all_right: false, // 是否全对
+      select_index: null, // 点击拖动时选中的小题数
     };
   },
   watch: {
     move_list: {
       handler(val) {
         if (!val || this.isJudgingRightWrong) return;
-        this.answer.answer_list = val.map(({ mark }) => {
-          return mark;
+        this.answer.answer_list = val.map((item) => {
+          let answer_item = item.map((items) => {
+            return items.mark;
+          });
+          return answer_item;
         });
       },
       deep: true,
@@ -108,10 +116,13 @@ export default {
       handler(val) {
         if (!val) return;
 
-        this.move_list = this.answer.answer_list.map((item) => {
-          return {
-            ...this.data.option_list.find((items) => items.mark === item),
-          };
+        this.move_list = this.answer.answer_list.map((item, index) => {
+          let move_item = item.map((itemm) => {
+            return {
+              ...this.data.option_list[index].find((items) => items.mark === itemm),
+            };
+          });
+          return move_item;
         });
         this.is_all_right = JSON.stringify(this.answer.answer_list) === JSON.stringify(this.data.answer.answer_list);
       },
@@ -121,9 +132,15 @@ export default {
       handler(val) {
         if (!val) return;
         this.disrupted = false;
-        this.move_list = this.shuffle(val.slice()).map((item) => ({
-          ...item,
-        }));
+        this.move_list = val.slice().map((item, index) => {
+          let shuffe_item = this.shuffle(item.slice()).map(
+            (items) => ({
+              ...items,
+            }),
+            index === val.length - 1,
+          );
+          return shuffe_item;
+        });
       },
       deep: true,
       immediate: true,
@@ -136,15 +153,16 @@ export default {
       },
     },
   },
+  mounted() {},
   methods: {
     // 随机打乱数组顺序
-    shuffle(arr) {
+    shuffle(arr, flag) {
       if (this.disrupted) return arr;
       for (let i = arr.length - 1; i > 0; i--) {
         const j = Math.floor(Math.random() * (i + 1));
         [arr[i], arr[j]] = [arr[j], arr[i]];
       }
-      this.disrupted = true;
+      this.disrupted = flag;
       return arr;
     },
     onStart() {
@@ -153,26 +171,29 @@ export default {
     // 拖拽结束事件
     onEnd() {
       this.drag = false;
-      // this.changeuserAnswerJudge();
       this.$forceUpdate();
     },
-    // 判断对错
-    changeuserAnswerJudge() {
-      this.move_list.forEach((item, index) => {
-        item.correct = item.mark === this.data.option_list[index].mark;
-      });
-    },
     // 点击item
-    handleClickItem(indexNode) {
+    handleClickItem(index, indexNode) {
       // 查看答案模式下需要禁用
       if (this.disabled) return;
+      if (this.click_index_list.length !== 0) {
+        let indexs = this.select_index;
+        if (Number(indexs) !== Number(index)) {
+          this.click_index_list = [];
+        }
+      }
+      this.select_index = index;
       this.click_index_list.push(indexNode);
     },
     // 点击交换
     changeSort() {
-      [this.move_list[this.click_index_list[0]], this.move_list[this.click_index_list[1]]] = [
-        this.move_list[this.click_index_list[1]],
-        this.move_list[this.click_index_list[0]],
+      let indexs = this.select_index;
+      let index1 = this.click_index_list[0];
+      let index2 = this.click_index_list[1];
+      [this.move_list[indexs][index1], this.move_list[indexs][index2]] = [
+        this.move_list[indexs][index2],
+        this.move_list[indexs][index1],
       ];
       this.click_index_list = [];
     },
@@ -186,6 +207,15 @@ export default {
 .sort-preview {
   @include preview;
 
+  .move-box-horizontal {
+    display: flex;
+    column-gap: 8px;
+
+    .option-number {
+      line-height: 50px;
+    }
+  }
+
   .content-box {
     .drag-item {
       display: flex;