Преглед на файлове

练习题 选择题完善功能

dusenyao преди 1 година
родител
ревизия
1b8deb71d7

+ 5 - 8
src/components/common/RichText.vue

@@ -34,6 +34,7 @@ import 'tinymce/plugins/media'; // 插入视频插件
 // import 'tinymce/plugins/preview'; // 预览插件
 import 'tinymce/plugins/hr';
 import 'tinymce/plugins/autoresize'; // 自动调整大小插件
+import 'tinymce/plugins/ax_wordlimit'; // 字数限制插件
 
 import { getRandomNumber } from '@/utils';
 
@@ -79,20 +80,16 @@ export default {
         min_height: 52,
         width: '100%',
         autoresize_bottom_margin: 0,
-        plugins: 'link lists image hr media autoresize',
+        plugins: 'link lists image hr media autoresize ax_wordlimit',
         /* eslint-disable max-len */
         toolbar:
           'fontselect fontsizeselect forecolor backcolor | underline | bold italic strikethrough alignleft aligncenter alignright | bullist numlist | image media | link blockquote hr',
         menubar: false,
         branding: false,
         statusbar: false,
-        audio_template_callback: (data) => {
-          `<audio controls>\n` +
-            `<source src="${data.source}"${data.sourcemime ? ` type="${data.sourcemime}"` : ''} />\n${
-              data.altsource
-                ? `<source src="${data.altsource}"${data.altsourcemime ? ` type="${data.altsourcemime}"` : ''} />\n`
-                : ''
-            }</audio>`;
+        ax_wordlimit_num: 500,
+        ax_wordlimit_callback(editor) {
+          editor.execCommand('undo');
         }
       }
     };

+ 1 - 1
src/router/guard/index.js

@@ -4,7 +4,7 @@ import NProgress from 'nprogress';
 import 'nprogress/nprogress.css';
 NProgress.configure({ showSpinner: false });
 
-const whiteList = ['/login']; // 重定向白名单
+const whiteList = ['/login', '/EnterSys']; // 重定向白名单
 
 export function setupRouterGuard(router) {
   // 全局前置守卫

+ 21 - 0
src/router/modules/basic.js

@@ -1,4 +1,5 @@
 import DEFAULT from '@/layouts/default';
+import store from '@/store';
 
 export const LoginPage = {
   path: '/login',
@@ -6,6 +7,26 @@ export const LoginPage = {
   component: () => import('@/views/login')
 };
 
+export const EnterSys = {
+  path: '/EnterSys',
+  beforeEnter: (to, from, next) => {
+    store
+      .dispatch('user/enterSys')
+      .then(() => {
+        const { tab, enter, dateStamp } = to.query;
+        if (enter) {
+          next(`/${enter}?tab=${tab}&dateStamp=${dateStamp}`);
+        } else {
+          next('/');
+        }
+      })
+      .catch(() => {
+        store.dispatch('user/signOut');
+        next('/login');
+      });
+  }
+};
+
 export const HomePage = {
   path: '/',
   component: DEFAULT,

+ 7 - 0
src/store/modules/user.js

@@ -63,6 +63,13 @@ const actions = {
       commit(user.RESET_STATE);
       resolve();
     });
+  },
+
+  enterSys({ commit }) {
+    return new Promise((reslove) => {
+      commit(user.RESET_STATE);
+      reslove();
+    });
   }
 };
 

+ 33 - 0
src/utils/transform.js

@@ -13,3 +13,36 @@ export function digitToChinese(num) {
   }
   return str;
 }
+
+// 对小于 10 的补零
+export function zeroFill(val) {
+  if (val < 10) return `0${val}`;
+  return val;
+}
+
+/**
+ * 将秒转为 时:分:秒 格式
+ * @param {Number} val 秒
+ * @returns {String} hh:MM:ss
+ */
+export function secondFormatConversion(val) {
+  let second = parseInt(val); // 秒
+  if (second < 60) {
+    return `00:${second < 10 ? `0${second}` : second}`;
+  }
+  if (second < 3600) {
+    return `00:${zeroFill(parseInt(second / 60))}:${zeroFill(parseInt(second % 60))}`;
+  }
+  return `${zeroFill(parseInt(second / 60 / 60))}:${zeroFill(parseInt((second / 60) % 60))}:${zeroFill(
+    parseInt(second % 60)
+  )}`;
+}
+
+/**
+ * 将时间转为 时:分:秒 格式
+ * @param {Date} date 时间戳
+ * @returns {String} hh:MM:ss
+ */
+export function timeFormatConversion(date) {
+  return `${zeroFill(date.getHours())}:${zeroFill(date.getMinutes())}:${zeroFill(date.getSeconds())}`;
+}

+ 1 - 1
src/views/exercise_questions/create/components/exercises/QuestionBase.vue → src/views/exercise_questions/create/components/common/QuestionBase.vue

@@ -13,7 +13,7 @@
 </template>
 
 <script>
-import SelectQuestionType from '../SelectQuestionType.vue';
+import SelectQuestionType from './SelectQuestionType.vue';
 
 export default {
   name: 'QuestionBase',

+ 0 - 0
src/views/exercise_questions/create/components/SelectQuestionType.vue → src/views/exercise_questions/create/components/common/SelectQuestionType.vue


+ 23 - 0
src/views/exercise_questions/create/components/common/UploadAudio.vue

@@ -0,0 +1,23 @@
+<template>
+  <div class="upload-audio">
+    <el-upload :limit="1">
+      <span>上传音频</span>
+    </el-upload>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'UploadAudio',
+  data() {
+    return {};
+  },
+  methods: {}
+};
+</script>
+
+<style lang="scss" scoped>
+.upload-audio {
+  display: flex;
+}
+</style>

+ 14 - 8
src/views/exercise_questions/create/components/create.vue

@@ -34,6 +34,9 @@
 </template>
 
 <script>
+import { SaveQuestion } from '@/api/exercise';
+import { timeFormatConversion } from '@/utils/transform';
+
 import SelectQuestion from './exercises/SelectQuestion.vue';
 
 export default {
@@ -72,7 +75,7 @@ export default {
   },
   mounted() {
     setInterval(() => {
-      this.saveData();
+      this.saveQuestion();
     }, 30000);
   },
   methods: {
@@ -125,15 +128,18 @@ export default {
       };
     },
     /**
-     * 保存数据
+     * 保存题目
      */
-    saveData() {
+    async saveQuestion() {
       if (this.indexList.length <= 0) return;
-      this.$emit('saveQuestion', this.dataConversion());
-      const date = new Date();
-      const curDate = `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
-      if (this.curSaveDate !== curDate) {
-        this.curSaveDate = curDate;
+      try {
+        await SaveQuestion(this.dataConversion());
+        const curDate = timeFormatConversion(new Date());
+        if (this.curSaveDate !== curDate) {
+          this.curSaveDate = curDate;
+        }
+      } catch (err) {
+        console.log(err);
       }
     }
   }

+ 14 - 2
src/views/exercise_questions/create/components/exercises/SelectQuestion.vue

@@ -59,6 +59,16 @@
         <el-form-item label="题号">
           <el-input v-model="data.setting.question_number" disabled />
         </el-form-item>
+        <el-form-item label-width="45px">
+          <el-radio
+            v-for="{ value, label } in questionNumberTypeList"
+            :key="value"
+            v-model="data.setting.question_number_type"
+            :label="value"
+          >
+            {{ label }}
+          </el-radio>
+        </el-form-item>
         <el-form-item label="描述">
           <el-radio
             v-for="{ value, label } in switchOption"
@@ -104,7 +114,7 @@
 </template>
 
 <script>
-import QuestionBase from './QuestionBase.vue';
+import QuestionBase from '../common/QuestionBase.vue';
 import RichText from '@/components/common/RichText.vue';
 
 import {
@@ -112,7 +122,8 @@ import {
   selectTypeList,
   switchOption,
   scoreTypeList,
-  computeOptionMethods
+  computeOptionMethods,
+  questionNumberTypeList
 } from '@/views/exercise_questions/data/common';
 import { selectData, selectType } from '@/views/exercise_questions/data/select';
 import { GetQuestion } from '@/api/exercise';
@@ -137,6 +148,7 @@ export default {
       selectTypeList,
       switchOption,
       scoreTypeList,
+      questionNumberTypeList,
       data: JSON.parse(JSON.stringify(selectData))
     };
   },

+ 1 - 13
src/views/exercise_questions/create/index.vue

@@ -28,7 +28,6 @@
       @setUp="setUp"
       @setPreview="setPreview"
       @deleteQuestion="deleteQuestion"
-      @saveQuestion="saveQuestion"
       @addQuestionToExercise="addQuestionToExercise"
     />
 
@@ -127,17 +126,6 @@ export default {
         });
     },
     /**
-     * 保存题目
-     * @param {object} data
-     */
-    async saveQuestion(data) {
-      try {
-        await SaveQuestion(data);
-      } catch (err) {
-        console.log(err);
-      }
-    },
-    /**
      * 获取练习题目索引列表
      */
     getExerciseQuestionIndexList() {
@@ -165,7 +153,7 @@ export default {
     selectExerciseItem(index, data) {
       if (index < 0 || index > this.index_list.length - 1) return;
       this.curIndex = index;
-      this.saveQuestion(data);
+      this.$refs.createMain.saveQuestion(data);
     },
     // 设置
     setUp() {

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

@@ -52,3 +52,9 @@ export const switchOption = [
   { value: true, label: '开启' },
   { value: false, label: '关闭' }
 ];
+
+// 题号类型
+export const questionNumberTypeList = [
+  { value: 'recalculate', label: '重新计算' },
+  { value: 'follow', label: '跟随上题' }
+];

+ 9 - 1
src/views/exercise_questions/data/select.js

@@ -1,4 +1,11 @@
-import { optionTypeList, stemTypeList, selectTypeList, scoreTypeList, questionTypeOption } from './common';
+import {
+  optionTypeList,
+  stemTypeList,
+  selectTypeList,
+  scoreTypeList,
+  questionTypeOption,
+  questionNumberTypeList
+} from './common';
 import { getRandomNumber } from '@/utils/index';
 
 // 选择题数据模板
@@ -18,6 +25,7 @@ export const selectData = {
   setting: {
     stem_type: stemTypeList[0].value, // 题干类型
     question_number: 1, // 题号
+    question_number_type: questionNumberTypeList[0].value, // 题号类型
     is_describe: false, // 描述
     select_type: selectTypeList[0].value, // 选择类型
     is_hear: true, // 是否听力

+ 8 - 9
src/views/exercise_questions/preview/SelectPreview.vue

@@ -39,15 +39,14 @@ export default {
   },
   computed: {
     list() {
-      // 将数组中的顺序随机打乱
-      const arr = JSON.parse(JSON.stringify(this.data.options));
-      const newArr = [];
-      while (arr.length > 0) {
-        const randomIndex = Math.floor(Math.random() * arr.length);
-        newArr.push(arr[randomIndex]);
-        arr.splice(randomIndex, 1);
+      const list = [...this.data.options];
+      for (let i = list.length - 1; i >= 0; i--) {
+        const randomIndex = Math.floor(Math.random() * (i + 1));
+        const itemAtIndex = list[randomIndex];
+        list[randomIndex] = list[i];
+        list[i] = itemAtIndex;
       }
-      return newArr;
+      return list;
     }
   },
   methods: {
@@ -128,7 +127,7 @@ export default {
 
         .selectionbox {
           border-color: #306eff;
-          border-width: 10px;
+          border-width: 4px;
         }
       }