Parcourir la source

添加单选题/多选题的题目信息添加以及试卷的模拟保存

lm il y a 1 mois
Parent
commit
5ece0409b2

+ 4 - 1
src/baseComponents/Form.vue

@@ -405,9 +405,12 @@ const props = defineProps({
 })
 const emit  = defineEmits(['close','confirm','formItemChange','fileUpload'])
 
+const formRef = defineModel('formRef')
+
+
 const fileMessage = ref({})
 const formData = ref({})
-const formRef = ref()
+// const formRef = ref()
 
 const finalFormItemList = computed(()=>{
     return props.formItemList.filter(item=>!item.hidden)

+ 79 - 45
src/components/testQuestionConfig/TestQuestionConfig.vue → src/components/questionConfig/QuestionConfig.vue

@@ -2,16 +2,18 @@
     <div class="test_question_config">
         <Form
             :form-item-list="finalFormItemList"
-            :default-form-data="formData"
+            :default-form-data="defaultFormData"
             @form-item-change="HandleFormItemChange"
             labelWidth="92px"
         >
-
             <template #questionType>
                 <div class="question_type">
-                        <!-- @change="(val)=>handleSelectChange(item.key,val)" -->
-                        <!-- v-model="formData[item.key]"  :style="item.style" :disabled="item.disabled" :placeholder="item.placeholder" -->
-                    <el-select class="type_select">
+                    <!-- 题目类型下拉 -->
+                    <el-select   
+                        v-model="defaultFormData.questionType" 
+                        class="type_select"
+                        @change="(val)=>HandleQuestionTypeChange('question_type',val)"
+                        placeholder="请选择">
                         <el-option
                             v-for="selectItem in questionTypeOptions"
                             :key="selectItem.value"
@@ -20,11 +22,10 @@
                         />
                     </el-select>
 
-
-                    <!-- v-model="formData[item.key] " -->
-                    <!-- @change="(val)=>handleSelectChange(item.key,val,item.type,item.selectList)" -->
+                    <!-- 题目额外 展示配置 -->
                     <el-checkbox-group  
                         class="type_cofig_check"
+                        v-model="defaultFormData.extraConfig"
                     >
                         <el-checkbox 
                             v-for="checkItem in questionConfig" 
@@ -37,7 +38,7 @@
             </template>
             <template #options="{ formData }">
                 <div class="options_list_container">
-                    <div v-for="(option, index) in formData.options" :key="option.id" class="option_item">
+                    <div v-for="(option) in formData.options" :key="option.id" class="option_item">
                         <div class="input_option">
                             <el-input 
                                 v-model="option.content" 
@@ -46,7 +47,7 @@
                             <template v-if="displayMode === 'statistic'">
                                 <el-icon 
                                     class="delete_icon" 
-                                    @click="removeOption(index)"
+                                    @click="removeOption(option.id)"
                                 >
                                     <Close/>
                                 </el-icon>
@@ -62,7 +63,7 @@
                             />
                             <el-icon 
                                 class="delete_icon" 
-                                @click="removeOption(index)"
+                                @click="removeOption(option.id)"
                             >
                                 <Close/>
                             </el-icon>
@@ -80,9 +81,9 @@
                 </div>
             </template>
 
-            <template #submit>
+            <template #submit="{formRef,formData}">
                 <div class="action_bar">
-                    <el-button class="button_background">确定</el-button>
+                    <el-button class="button_background" @click="HandleAddConfirm({formRef,formData})">确定</el-button>
                     <el-button class="button_refresh">取消</el-button>
                 </div>
             </template>
@@ -96,7 +97,6 @@ import { Close, CirclePlus } from '@element-plus/icons-vue'
 import Form from '@/baseComponents/Form.vue'
 
 import { questionFormItemList } from './form'
-
 import {
     statisticQuestionType, scoredQuestionType, questionConfig
 } from './questionTypeList'
@@ -110,38 +110,41 @@ interface Option {
 }
 
 interface FormData {
-    title: String
-    titleScore?: String
-    questionType: String
-    isRequired: String[]  
-    options: Option[]
+    title: String   //题目名称
+    titleScore?: String  //题目分值
+    questionType: String   //题目类型
+    extraConfig: String[]    // 是否必答 required, 是否横排 isHorizontal
+    options: Option[]  //单选/多选 的 选项配置
 }
 
 const props = defineProps({
-    displayMode: {
+    displayMode: {     // 展示形式  带分值 scored 不带分值 statistic
         type: String as () => DisplayMode,
         default: 'statistic',
         required:true,
     },
-    questionType: {
-        type: String,
+    questionType: {   //默认的题目类型
+        type: String, 
         default: ''
     }
 })
-
 const emit = defineEmits(['confirm', 'cancel', 'form-change'])
 
-const formData = ref<FormData>({
-    title: '',
-    titleScore: '',
-    questionType: '',
-    isRequired: ['required'],
-    options: [
-        // { content: '', score: '',id:1 },
-    ]
-})
+// 题目信息 
+const defaultFormData = ref<FormData>({
+    title: '',  
+    titleScore: '',   
+    questionType: '', 
+    extraConfig: ['required'],  
+    options: []  
+ })
 
 
+
+/*
+  监听 props.displayMode 展示 不同的 题型配置 和 试卷配置 
+*/
+// 题型选项配置 监听 动态切换
 const questionTypeOptions = computed(() => {
     if (props.displayMode === 'scored') {
         return [...scoredQuestionType.value]
@@ -149,8 +152,7 @@ const questionTypeOptions = computed(() => {
         return  [... statisticQuestionType.value]
     }
 })
-
-
+// 表单试卷 展示项配置  监听 动态显隐
 const finalFormItemList = computed(() => {
     return questionFormItemList.value.map(item => {
         const newItem = { ...item }
@@ -162,28 +164,60 @@ const finalFormItemList = computed(() => {
     })
 })
 
-watch(() => props.questionType, (newVal) => {
-    if (newVal) {
-        formData.value.questionType = newVal
-    }
-}, { immediate: true })
 
-watch(formData, (newVal) => {
-    emit('form-change', newVal)
-}, { deep: true })
+// 题目类型变化触发的操作
+const HandleQuestionTypeChange = (key,val)=>{
+    // 
+
+}
+
 
+
+// 表单内部某些变化 触发 的操作
 const HandleFormItemChange = (params: any) => {
     const { key, val, formData: data } = params
+    // console.log('表单项目变化了--',formData)
     emit('form-change', data)
 }
 
+// 添加题目选项配置
 const addOption = () => {
-    formData.value.options.push({ content: '', score: '',id:(Number(formData.value.options[formData.value.options.length - 1]?.id || 0) + 1) })
+    defaultFormData.value.options.push({ content: '', score: '',id:(Number(defaultFormData.value.options[defaultFormData.value.options.length - 1]?.id || 0) + 1) })
+}
+// 删除题目选项配置
+const removeOption = (id: number) => {
+    defaultFormData.value.options = defaultFormData.value.options.filter((opt)=>{
+        return opt.id !== id
+    })
 }
 
-const removeOption = (index: number) => {
-    formData.value.options.splice(index, 1)
+// 题目信息校验 并传递信息给父级
+const HandleAddConfirm = async (params:any)=>{
+    const {formRef,formData} = params
+    if (!formRef) return
+    await formRef.validate(async(valid) => {
+        if (valid) {
+            emit('confirm', {formData:formData,formRef})
+        }
+    }).catch(err=>{
+        console.log('报错信息',err)
+    })
 }
+
+// 修改题型的默认展示值
+watch(() => props.questionType, (newVal) => {
+    if (newVal) {
+        defaultFormData.value.questionType = newVal
+    }
+}, { immediate: true })
+
+// 表单信息变化触发的操作
+watch(()=>defaultFormData.value, (newVal) => {
+    emit('form-change', newVal)
+}, { deep: true })
+
+
+
 </script>
 
 <style lang="scss" scoped>

+ 44 - 0
src/components/questionConfig/QuestionnaireBaseForm.vue

@@ -0,0 +1,44 @@
+<template>
+    <Form 
+        :defaultFormData="formData" 
+        :formItemList="questionnaireBaseForm"
+        :inlineLayout="false"
+        v-model:formRef="formRef"
+    ></Form>
+</template>
+
+
+<script setup lang="ts">
+import {ref,watch} from 'vue'
+import Form from '@/baseComponents/Form.vue';
+import {questionnaireBaseForm,} from './form'
+
+interface FormItm {
+    questionnaireTitle:String,
+    questionnaireDesc:String
+}
+
+const props = defineProps({
+    defaultFormData:{
+        type:Object as () => FormItm,
+        required:true
+    }
+})
+const emit = defineEmits(['formChage'])
+
+const formRef = defineModel('formRef')
+
+const formData = ref({})
+
+watch(()=>props.defaultFormData,(newVal)=>{
+    formData.value = {...newVal}
+})
+
+watch(()=>formData.value,(newVal)=>{
+    emit('formChage',newVal)
+},{deep:true})
+
+</script>
+
+
+<style lang="scss" scoped></style>

+ 21 - 3
src/components/testQuestionConfig/form.ts → src/components/questionConfig/form.ts

@@ -7,7 +7,13 @@ export const questionFormItemList = ref([
         label: '题目',
         type: 'input',
         placeholder: '请输入题目',
-        rules: [],
+        rules: [
+            {
+                required:true,
+                message:'请填写信息',
+                trigger:'blur'
+            }
+        ],
         hidden: false,
         disabled: false,
         custom: false,
@@ -19,7 +25,13 @@ export const questionFormItemList = ref([
         label: '题目分值',
         type: 'input',
         placeholder: '请输入分值',
-        rules: [],
+        rules: [
+            {
+                required:true,
+                message:'请填写信息',
+                trigger:'blur'
+            }
+        ],
         style: {marginRight:'40px'},
         className: 'percent_30'
     },
@@ -29,7 +41,13 @@ export const questionFormItemList = ref([
         type: 'select',
         selectList: [],
         placeholder: '',
-        rules: [],
+        rules: [
+            {
+                required:true,
+                message:'请填写信息',
+                trigger:'blur'
+            }
+        ],
         style: {},
         custom:true,
         // className: 'percent_40'

+ 15 - 0
src/components/testQuestionConfig/questionTypeList.ts → src/components/questionConfig/questionTypeList.ts

@@ -48,3 +48,18 @@ export const questionConfig = ref([
     { label: '必答题', value: 'required' },
     { label: '选项横排', value: 'isHorizontal' }
 ])
+
+export const qustionTypeToName = (type)=>{
+    switch(Number(type)){
+        case 0:
+            return '单选题'
+        case 1:
+            return '多选题'
+        case 2:
+            return '问答题'
+        case 3:
+            return '评分单选题'
+        case 4:
+            return '评价题'
+    }
+}

+ 0 - 24
src/components/testQuestionConfig/QuestionnaireBaseForm.vue

@@ -1,24 +0,0 @@
-<template>
-    <Form 
-        :defaultFormData="defaultFormData" 
-        :formItemList="questionnaireBaseForm"
-        :inlineLayout="false"
-    ></Form>
-</template>
-
-
-<script setup lang="ts">
-import Form from '@/baseComponents/Form.vue';
-import {questionnaireBaseForm} from './form'
-
-const props = defineProps({
-    defaultFormData:{
-        type:Object,
-        required:true
-    }
-})
-
-</script>
-
-
-<style lang="scss" scoped></style>

+ 13 - 6
src/views/surveyManagement/SurveyManagement.vue

@@ -26,7 +26,7 @@
                     <div class="card_header">
                         <!-- 模拟图片中的文档图标 -->
                         <img src="" alt="" class="card-icon" />
-                        <span class="card_title two_line_ellipsis">{{ quesitonnaire.title }}</span>
+                        <span class="card_title two_line_ellipsis">{{ quesitonnaire.questionnaireTitle }}</span>
                     </div>
 
                     <!-- 中间区域:元数据 (分数、创建人、状态、时间) -->
@@ -98,7 +98,7 @@ import { questionnaireTableColumns } from './table';
 import {useStatusConvert} from './useStatus'
 interface QuestionnaireItm {
     id:Number,
-    title:String,
+    questionnaireTitle:String,
     totalScore:Number|String,
     createBy:String,
     createTime:String,
@@ -124,7 +124,7 @@ const pageSize = ref(20)
 const questionnaireList = ref<QuestionnaireItm[]>([
     {
         id:1,
-        title: "作业量满意度问卷",
+        questionnaireTitle: "作业量满意度问卷",
         totalScore: 100,
         createBy: "管理员",
         createTime: "2024-10-08 16:00",
@@ -132,7 +132,7 @@ const questionnaireList = ref<QuestionnaireItm[]>([
     },
     {
         id:2,
-        title: "作业量满意度问卷作业量满意度问卷作业量满意度问卷作度问卷作业量满意度问卷作度问卷作业量满意度问卷作度问卷作业量满意度问卷作业量满意度问卷卷...",
+        questionnaireTitle: "作业量满意度问卷作业量满意度问卷作业量满意度问卷作度问卷作业量满意度问卷作度问卷作业量满意度问卷作度问卷作业量满意度问卷作业量满意度问卷卷...",
         totalScore: 100,
         createBy: "管理员",
         createTime: "2024-10-08 16:00",
@@ -140,7 +140,7 @@ const questionnaireList = ref<QuestionnaireItm[]>([
     },
     {
         id:3,
-        title: "作业量满意度问卷",
+        questionnaireTitle: "作业量满意度问卷",
         totalScore: 100,
         createBy: "管理员",
         createTime: "2024-10-08 16:00",
@@ -148,7 +148,7 @@ const questionnaireList = ref<QuestionnaireItm[]>([
     },
      {
         id:4,
-        title: "作业量满意度问卷",
+        questionnaireTitle: "作业量满意度问卷",
         totalScore: 100,
         createBy: "管理员",
         createTime: "2024-10-08 16:00",
@@ -158,6 +158,13 @@ const questionnaireList = ref<QuestionnaireItm[]>([
 ]);
 
 
+onMounted(()=>{
+    /**
+     * 模拟数据
+     */
+    questionnaireList.value = JSON.parse(localStorage.getItem('questionnaireList') || '[]')
+})
+
 
 
 </script>

+ 223 - 19
src/views/surveyManagement/createQuestionnaire/CreateQuestionnaire.vue

@@ -4,21 +4,21 @@
             <template #topRight>
                 <span class="paper_score">阅卷总分:<span class="score">60分</span></span>
                 <el-button class="button_refresh">预览问卷</el-button>
-                <el-button class="button_background">保存问卷</el-button>
+                <el-button class="button_background" @click="HandleQuestionnaireSave">保存问卷</el-button>
             </template>
         </TopBackNav>
 
-        <div class="page_jg_20"></div>
+        <div class="page_jg_20" style="flex-shrink: 0;"></div>
 
         <div class="questionnaire_config" >
-            <div class="left_panel">
+            <div  class="left_panel">
                 <div class="panel_section page_item">
                     <h3 class="section_title">统计题</h3>
                     <!-- 题型循环 -->
                     <div class="type_list">
                         <template v-for="typeItm in statisticQuestionType" :key="typeItm.value">
                             <el-button class="button_refresh" 
-                                        @click="HandleQuestionTypeSelect(typeItm.value)" >
+                                        @click="CheckedQuestionType(typeItm.value)" >
                                 <img :src="typeItm.icon" alt="">
                                  {{ typeItm.label }}
                             </el-button>
@@ -32,7 +32,7 @@
                     <div class="type_list">
                         <template v-for="typeItm in scoredQuestionType" :key="typeItm.value">
                             <el-button class="button_refresh"
-                                     @click="HandleQuestionTypeSelect(typeItm.value)">
+                                     @click="CheckedQuestionType(typeItm.value)">
                                 <img :src="typeItm.icon" alt="">
                                  {{ typeItm.label }}
                             </el-button>
@@ -44,16 +44,71 @@
             <!-- 中间面板:编辑区域 -->
             <div class="center_panel">
                 <div class="page_item questionnaire_base">
-                    <QuestionnaireBaseForm :defaultFormData="{}"></QuestionnaireBaseForm>
+                    <!-- questionnaireInfo -->
+                    <QuestionnaireBaseForm 
+                        v-model:formRef="questionnaireBaseFormRef" 
+                        :defaultFormData="{}"
+                        @formChage="SyncQuestionnaireFormData"
+                    ></QuestionnaireBaseForm>
                 </div>
 
+                <ul class="question_list_area">
+                    <li v-for="(question,index) in addedQuestionList" :key="question.id">
+                        <div class="question_title" 
+                            :class="{required:question.extraConfig.includes('required')}">
+                            {{index + 1}}.{{ question.title }}
+                            <span class="question_type">[{{ qustionTypeToName(question.questionType) }}]</span>
+                        </div>
+
+                        <!-- 单选  -->
+                        <el-radio-group 
+                            v-if="Number(question.questionType) === 0" 
+                            :class="{vertical:!question.extraConfig.includes('isHorizontal')}"> 
+
+                            <el-radio v-for="radioItem in question.options" :key="radioItem.value" :value="radioItem.value">{{ radioItem.label }}</el-radio>
+                        </el-radio-group>
+                            
+                        <!-- 多选 -->
+                        <el-checkbox-group 
+                            v-else-if="Number(question.questionType) === 1" 
+                            :class="{vertical:!question.extraConfig.includes('isHorizontal')}">
+
+                            <el-checkbox 
+                            v-for="checkItem in question.options" 
+                            :key="checkItem.value"
+                            :label="checkItem.label"
+                            :value="checkItem.value"
+                            />
+                        </el-checkbox-group>
+
+                        <!-- 问答题 -->
+                        <el-input  
+                            v-else-if="Number(question.questionType) === 2 || Number(question.questionType) === 4"
+                            :autosize="{ minRows:5, maxRows: 5 }" 
+                            type="textarea" 
+                            :rows="5"  
+                            placeholder="不超过2000字"
+                        />
+
+                        <!-- 评分题 3 -->
+
+
+                    </li>
+                </ul>
+
+
+
                 <!-- 题目添加区域 -->
                  <div class=" add_question_area">
                     <div v-if="!selectedQuestionType" class="add_question">
                         <div class="add_action">+ 点击左侧添加题型</div>
                     </div>
                     <div   v-else class="question_itm_edit">
-                        <TestQuestionConfig  :displayMode="selectedQuestionGetScore ? 'scored' : 'statistic'"></TestQuestionConfig>
+                        <QuestionConfig  
+                            :displayMode="selectedQuestionGetScore ? 'scored' : 'statistic'"
+                            :questionType="selectedQuestionType"
+                            @confirm="HandleAddQuesiton"
+                        ></QuestionConfig>
                     </div>
                  </div>
             </div>
@@ -69,21 +124,49 @@
 
 <script lang="ts" setup>
 import {onMounted, ref} from 'vue'
-
+import { useRouter } from 'vue-router';
 import TopBackNav from '@/components/TopBackNav.vue';
-import {statisticQuestionType,scoredQuestionType} from '../../../components/testQuestionConfig/questionTypeList'
-import TestQuestionConfig from '@/components/testQuestionConfig/TestQuestionConfig.vue';
-import Form from '@/baseComponents/Form.vue';
-import QuestionnaireBaseForm from '@/components/testQuestionConfig/QuestionnaireBaseForm.vue';
+import {statisticQuestionType,scoredQuestionType,qustionTypeToName} from '../../../components/questionConfig/questionTypeList'
+import QuestionConfig from '@/components/questionConfig/QuestionConfig.vue';
+import QuestionnaireBaseForm from '@/components/questionConfig/QuestionnaireBaseForm.vue';
+import { ElMessage } from 'element-plus';
+
 
+import { unioformDateTransform } from '@/utils/dateTransform';
 
-// 试卷基本信息
-const questionnaireInfo = ref({
-    title:'',
-    description:''
+// 题目选项信息 参数
+interface Option {
+    label: String
+    score?: String
+    value?: Number
+}
+// 题目信息 参数
+interface QuestionItm {
+    id:Number
+    title: String   //题目名称
+    titleScore?: String  //题目分值
+    questionType: String   //题目类型
+    extraConfig: String[]    // 是否必答 required, 是否横排 isHorizontal
+    options: Option[]  //单选/多选 的 选项配置
+}
+
+interface QuestionnaireInfo {
+    questionnaireTitle:String,
+    questionnaireDesc:String
+}
+
+
+const router = useRouter()
+
+// 试卷头表单
+const questionnaireBaseFormRef = ref()
+// 试卷头基本信息
+const questionnaireInfo = ref<QuestionnaireInfo>({
+    questionnaireTitle:'',
+    questionnaireDesc:''
 })
 // 已经添加的题型
-const addedQuestionTypes = ref([])
+const addedQuestionList = ref<QuestionItm[]>([])
 // 当前选中的题型
 const selectedQuestionType = ref('')
 // 选中题型的类型 // 得分题  true  非得分题 false 
@@ -92,7 +175,7 @@ const selectedQuestionGetScore = ref(false)
 
 
 // 选中题型时的处理
-const HandleQuestionTypeSelect = (type:any) => {
+const CheckedQuestionType = (type:any) => {
     selectedQuestionType.value = type
     switch(type){
         case '0':
@@ -106,6 +189,77 @@ const HandleQuestionTypeSelect = (type:any) => {
             break
     }
 }
+
+// 同步表单数据
+const SyncQuestionnaireFormData = (params)=>{
+    questionnaireInfo.value = {...params}
+}
+
+
+// 添加试题信息
+const HandleAddQuesiton = (params)=>{
+    const {formRef,formData} = params
+    console.log('获取到试题信息了',formData)
+
+    let id = (Number(addedQuestionList.value[addedQuestionList.value.length - 1]?.id || 0) + 1)
+    let options = formData.options.map(item=>{
+        return {
+            label:item.content,
+            value:item.id,
+            score:item.score
+        }
+    })
+    addedQuestionList.value.push({id ,...formData,options})
+    formRef.resetFields()
+    selectedQuestionType.value = ''
+}
+
+// 保存试卷
+const HandleQuestionnaireSave = async ()=>{
+    // 试卷总表单
+    let formRef = questionnaireBaseFormRef.value
+
+    if (!formRef) return
+    await formRef.validate(async(valid) => {
+        if (valid) {
+            if(addedQuestionList.value.length > 0){
+                let finalQuestionMsg = {
+                    ...(questionnaireInfo.value),
+                    quetionList:addedQuestionList.value
+                }
+                console.log('最终提交的表单信息',finalQuestionMsg)
+
+                /**
+                 * 模拟数据
+                 */
+                // 模拟保存数据 和页面跳转
+                let questionnaireList = JSON.parse(localStorage.getItem('questionnaireList') || '[]')
+                questionnaireList.push({
+                    ...finalQuestionMsg,
+                    id:Number(questionnaireList[questionnaireList.length - 1]?.id || 0) + 1,
+                    createTime:unioformDateTransform(new Date()),
+                    createBy:'管理员',
+                    totalScore:addedQuestionList.value.reduce((a,b)=>{
+                        let aScore =  Number(a.titleScore || 0)
+                        let bScore =  Number(b.titleScore || 0)
+                        return {
+                            titleScore:aScore + bScore
+                        }
+                    }).titleScore,
+                    useStatus:1
+                })
+                localStorage.setItem('questionnaireList',JSON.stringify(questionnaireList))
+                router.push('/main')
+            }else{
+                ElMessage.warning('请添加问卷题目')
+            }
+        }
+    }).catch(err=>{
+        console.log('报错信息',err)
+    })
+
+
+}
 </script>
 
 <style lang="scss" scoped>
@@ -133,10 +287,15 @@ const HandleQuestionTypeSelect = (type:any) => {
 .questionnaire_config {
     flex-grow: 1;
     display: flex;
+    justify-content: space-between;
     gap: 20px;
+
+    position: relative;
     
     /* --- 左侧面板 --- */
     .left_panel {
+        position: fixed;
+        left: 20px;
         width: 200px;
         display: flex;
         flex-direction: column;
@@ -177,9 +336,11 @@ const HandleQuestionTypeSelect = (type:any) => {
 
     /* --- 中间面板 --- */
     .center_panel {
-        flex: 1; /* 占据剩余空间 */
+        width: calc(100vw - 440px - 80px);
+        margin-left: calc(200px + (100% - 440px -  calc(100vw - 440px - 80px))/2);
         display: flex;
         flex-direction: column;
+        border-radius: 10px;
 
         background-color: white;
 
@@ -187,7 +348,46 @@ const HandleQuestionTypeSelect = (type:any) => {
             border-radius:10px 10px 0 0;
             padding-bottom: 0;
         }
+        
+        // 已添加试题区
+        .question_list_area{
+            display: flex;
+            flex-direction: column;
+            gap:20px;
+            padding:20px;
+            font-size: 14px;
+            color:#000;
+            li{
+                .question_title{
+                    margin-bottom: 20px;
+                    .question_type{
+                        color:#2E64FA;
+                        margin-left: 8px;
+                    }
+
+                    &.required{
+                        position: relative;
+                        padding-left: 5px;
+                        ::before{
+                            content:'*';
+                            position: absolute;
+                            left:0;
+                            color:#F56C6C;
+                        }
+                    }
+                }
+
+                .el-checkbox-group.vertical,
+                .el-radio-group.vertical{
+                    display: flex;
+                    flex-direction: column;
+                    justify-content: flex-start;
+                    align-items: flex-start;
+                }
+            }
+        }
 
+        // 添加试题区域
         .add_question_area{
             .add_question {
                 // flex-grow: 0;
@@ -213,7 +413,11 @@ const HandleQuestionTypeSelect = (type:any) => {
 
     /* --- 右侧面板 --- */
     .right_panel {
+        position: fixed;
+        right: calc(20px + 6px);
+        align-self: flex-start;
         width: 240px;
+        min-height: calc(100vh - 156px - 40px);
         display: flex;
         flex-direction: column;
         .empty_state {

+ 1 - 1
src/views/surveyManagement/table.ts

@@ -20,7 +20,7 @@ export const questionnaireTableColumns = ref([
         hidden: false,
     },
     {
-        name: 'title',
+        name: 'questionnaireTitle',
         label: '问卷名称',
         width: '250',
         fixed: '',