2 Commits 3e2079ae7a ... b10afb2e62

Author SHA1 Message Date
  dsy b10afb2e62 Merge branch 'master' of http://60.205.254.193:3000/GCLS/eep_page 1 week ago
  dsy d8585d7128 选择题增加单选多选设置 1 week ago

+ 1 - 1
.env

@@ -11,4 +11,4 @@ VUE_APP_BookWebSI = '/GCLSBookWebSI/ServiceInterface'
 VUE_APP_EepServer = '/EEPServer/SI'
 
 #version
-VUE_APP_VERSION = '2025.11.17'
+VUE_APP_VERSION = '2025.11.28'

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "eep_page",
-  "version": "2025.11.17",
+  "version": "2025.11.28",
   "private": true,
   "main": "main.js",
   "description": "智慧梧桐数字教材编辑器",

+ 21 - 0
src/components/CommonPreview.vue

@@ -1,7 +1,11 @@
 <template>
   <div class="common-preview">
     <div class="common-preview__header">
+      <div class="menu-container">
+        {{ courseware_info.book_name }}
+      </div>
       <div class="courseware">
+        <span class="name-path">{{ courseware_info.name_path }}</span>
         <span class="flow-nodename">{{ courseware_info.cur_audit_flow_node_name }}</span>
         <slot name="middle" :courseware="courseware_info"></slot>
         <div class="group">
@@ -1079,6 +1083,14 @@ $total-width: $courseware-width + $courseware-left-margin + $courseware-right-ma
     border-top: $border;
     border-bottom: $border;
 
+    > .menu-container {
+      display: flex;
+      justify-content: space-between;
+      width: 360px;
+      padding: 4px 8px;
+      border-right: $border;
+    }
+
     > .courseware {
       display: flex;
       flex-grow: 1;
@@ -1087,6 +1099,15 @@ $total-width: $courseware-width + $courseware-left-margin + $courseware-right-ma
       justify-content: space-between;
       height: 40px;
 
+      .name-path {
+        min-width: 200px;
+        height: 40px;
+        padding: 4px 8px;
+        font-size: 14px;
+        line-height: 32px;
+        border-right: $border;
+      }
+
       .lang-select {
         :deep .el-input {
           width: 100px;

+ 39 - 8
src/views/book/courseware/create/components/question/select/Select.vue

@@ -5,7 +5,10 @@
         <li v-for="(item, i) in data.option_list" :key="item.mark" class="option-item">
           <span class="serial-number">{{ computedOptionNumber(i) }}.</span>
           <div class="option-contnet">
-            <span :class="['checkbox', { active: isAnswer(item.mark) }]" @click="selectAnswer(item.mark)">
+            <span
+              :class="[isSingle ? 'radio' : 'checkbox', { active: isAnswer(item.mark) }]"
+              @click="selectAnswer(item.mark)"
+            >
               <SvgIcon icon-class="check-mark" width="10" height="7" />
             </span>
             <RichText
@@ -57,7 +60,7 @@
 import ModuleMixin from '../../common/ModuleMixin';
 import PinyinText from '@/components/PinyinText.vue';
 
-import { getSelectData, getOption, arrangeTypeList } from '@/views/book/courseware/data/select';
+import { getSelectData, getOption, arrangeTypeList, selectTypeList } from '@/views/book/courseware/data/select';
 import { serialNumberTypeList, computeOptionMethods } from '@/views/book/courseware/data/common';
 
 export default {
@@ -72,6 +75,11 @@ export default {
       curSelectIndex: -1,
     };
   },
+  computed: {
+    isSingle() {
+      return this.data.property?.select_type === selectTypeList[0].value;
+    },
+  },
   watch: {
     'data.property.arrange_type': 'handlerMindMap',
     'data.answer.answer_list': 'handlerMindMap',
@@ -97,6 +105,13 @@ export default {
       },
       deep: true,
     },
+    'data.property.select_type': {
+      handler() {
+        if (this.isSingle && this.data.answer.answer_list.length > 1) {
+          this.data.answer.answer_list = [this.data.answer.answer_list[0]];
+        }
+      },
+    },
   },
   methods: {
     computedOptionNumber(number) {
@@ -120,12 +135,17 @@ export default {
      * @param {string} mark 选项标记
      */
     selectAnswer(mark) {
-      const index = this.data.answer.answer_list.indexOf(mark);
-      if (index === -1) {
-        this.data.answer.answer_list.push(mark);
-      } else {
-        this.data.answer.answer_list.splice(index, 1);
+      if (mark === null || mark === undefined) return;
+
+      const list = this.data.answer.answer_list || [];
+      const isSelected = list.includes(mark);
+
+      if (this.isSingle) {
+        this.data.answer.answer_list = isSelected ? [] : [mark];
+        return;
       }
+
+      this.data.answer.answer_list = isSelected ? list.filter((item) => item !== mark) : list.concat(mark);
     },
     /**
      * @description 添加选项
@@ -146,7 +166,8 @@ export default {
     },
     handlerMindMap() {
       const direction = this.data.property.arrange_type === arrangeTypeList[0].value ? '横排' : '竖排';
-      const select = this.data.answer.answer_list.length > 1 ? '多选' : '单选';
+      const select =
+        this.data.property?.select_type === selectTypeList[1].value ? selectTypeList[1].label : selectTypeList[0].label;
       this.data.mind_map.node_list = [{ name: `${direction}${select}选择题` }];
     },
     openMultilingual(i) {
@@ -190,6 +211,7 @@ export default {
       overflow: hidden;
       background-color: $fill-color;
 
+      .radio,
       .checkbox {
         display: flex;
         align-items: center;
@@ -214,6 +236,15 @@ export default {
           }
         }
       }
+
+      .radio {
+        border-radius: 50%;
+
+        &.active {
+          background-color: #fff;
+          box-shadow: inset 0 0 0 4px #000;
+        }
+      }
     }
 
     .delete,

+ 8 - 1
src/views/book/courseware/create/components/question/select/SelectSetting.vue

@@ -8,6 +8,12 @@
         <SvgIcon icon-class="switch" height="16" width="16" @click="switchSNType" />
       </el-form-item>
 
+      <el-form-item label="选择类型">
+        <el-radio v-for="{ value, label } in selectTypeList" :key="value" v-model="property.select_type" :label="value">
+          {{ label }}
+        </el-radio>
+      </el-form-item>
+
       <el-form-item label="排列">
         <el-radio
           v-for="{ value, label } in arrangeTypeList"
@@ -49,7 +55,7 @@
 <script>
 import SettingMixin from '@/views/book/courseware/create/components/common/SettingMixin';
 
-import { arrangeTypeList, getSelectProperty } from '@/views/book/courseware/data/select';
+import { arrangeTypeList, getSelectProperty, selectTypeList } from '@/views/book/courseware/data/select';
 import { serialNumberTypeList } from '@/views/book/courseware/data/common';
 
 export default {
@@ -58,6 +64,7 @@ export default {
   data() {
     return {
       arrangeTypeList,
+      selectTypeList,
       property: getSelectProperty(),
     };
   },

+ 6 - 0
src/views/book/courseware/data/select.js

@@ -9,6 +9,11 @@ import { getRandomNumber } from '@/utils';
 
 export { arrangeTypeList };
 
+export const selectTypeList = [
+  { value: 'single', label: '单选' },
+  { value: 'multiple', label: '多选' },
+];
+
 /**
  * 获取选择题属性
  */
@@ -19,6 +24,7 @@ export function getSelectProperty() {
     sn_position: serialNumberPositionList[3].value,
     sn_display_mode: displayList[0].value,
     arrange_type: arrangeTypeList[0].value,
+    select_type: selectTypeList[0].value,
     option_serial_type: serialNumberTypeList[2].value,
     view_pinyin: 'false', // 显示拼音
     pinyin_position: pinyinPositionList[0].value,

+ 0 - 1
src/views/book/courseware/preview/components/fill/FillPreview.vue

@@ -279,7 +279,6 @@ export default {
       if (!isHasAudio) {
         _list[0].value = '0px';
       }
-      console.log(_list);
 
       if (!isFront) {
         _list = _list.reverse();

+ 27 - 8
src/views/book/courseware/preview/components/select/SelectPreview.vue

@@ -15,7 +15,7 @@
           :class="['option-item', { active: isAnswer(mark) }, ...computedAnswerClass(mark)]"
           @click="selectAnswer(mark)"
         >
-          <span class="checkbox">
+          <span :class="[isSingle ? 'radio' : 'checkbox']">
             <SvgIcon icon-class="check-mark" width="10" height="7" />
           </span>
           <span class="serial-number"> {{ computedOptionNumber(i) }}. </span>
@@ -44,7 +44,7 @@
 <script>
 import PreviewMixin from '../common/PreviewMixin';
 
-import { getSelectData, arrangeTypeList } from '@/views/book/courseware/data/select';
+import { getSelectData, arrangeTypeList, selectTypeList } from '@/views/book/courseware/data/select';
 import { serialNumberTypeList, computeOptionMethods } from '@/views/book/courseware/data/common';
 
 export default {
@@ -56,6 +56,11 @@ export default {
       arrangeTypeList,
     };
   },
+  computed: {
+    isSingle() {
+      return this.data.property?.select_type === selectTypeList[0].value;
+    },
+  },
   watch: {
     'answer.answer_list': {
       handler(val) {
@@ -83,13 +88,16 @@ export default {
     },
     selectAnswer(mark) {
       if (this.disabled) return;
+-
+      const list = this.answer.answer_list || [];
+      const isSelected = list.includes(mark);
 
-      const index = this.answer.answer_list.indexOf(mark);
-      if (index === -1) {
-        this.answer.answer_list.push(mark);
-      } else {
-        this.answer.answer_list.splice(index, 1);
+      if (this.isSingle) {
+        this.answer.answer_list = isSelected ? [] : [mark];
+        return;
       }
+
+      this.answer.answer_list = isSelected ? list.filter((item) => item !== mark) : list.concat(mark);
     },
     computedAnswerClass(mark) {
       if (!this.isJudgingRightWrong && !this.isShowRightAnswer) {
@@ -104,7 +112,7 @@ export default {
       }
       // 判断是否是正确答案
       if (isHas && this.isJudgingRightWrong) {
-        answerClass = isRight ? ['right'] : ['wrong'];
+        answerClass = isRight ? ['answer-right'] : ['wrong'];
       }
       return answerClass;
     },
@@ -141,6 +149,7 @@ export default {
         padding-left: 52px;
       }
 
+      .radio,
       .checkbox {
         display: flex;
         align-items: center;
@@ -158,6 +167,10 @@ export default {
         }
       }
 
+      .radio {
+        border-radius: 50%;
+      }
+
       .serial-number {
         font-size: 16pt;
       }
@@ -178,6 +191,11 @@ export default {
             display: block;
           }
         }
+
+        .radio {
+          background-color: #fff;
+          box-shadow: inset 0 0 0 4px $light-main-color;
+        }
       }
 
       &.answer-right {
@@ -192,6 +210,7 @@ export default {
       }
 
       &.wrong {
+        margin: 1px 0;
         background-color: $content-color;
         box-shadow: 0 0 0 1px $error-color;