|
|
@@ -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 {
|