ZhangXianQiang
2024-06-11 360f252566e55aae61f0bb17469cb28955dc32bc
feat:答题切换
7个文件已修改
356 ■■■■ 已修改文件
src/components/ExamInfo/index.vue 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/exam.js 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/user.js 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/exam/components/answer-main/answer-single/index.vue 43 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/exam/components/answer-sheet/index.vue 49 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/exam/index.vue 67 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ExamInfo/index.vue
@@ -1,7 +1,7 @@
<template>
  <div class="info-container w-full">
    <div class="exam-title break-all mb-4 text-base text-gray-700">
      1.测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试
      {{ title }}
    </div>
    <div class="img-container flex">
      <div class="img-item">
@@ -12,7 +12,16 @@
</template>
<script setup>
const props = defineProps({
  questionIndex: {
    type: Number,
    required: true
  },
  title: {
    type: String,
    required: true
  }
})
</script>
<style lang="scss" scoped>
src/router/index.js
@@ -5,7 +5,7 @@
const routes = [
  {
    path: '/',
    redirect: '/index'
    redirect: '/exam'
  },
  {
src/store/modules/exam.js
@@ -1,11 +1,175 @@
import { ref } from 'vue';
import { ref,computed } from 'vue';
import { defineStore } from 'pinia';
const useExamStore = defineStore('exam', () => {
  const examInfo = ref(null);
export const useExamStore = defineStore('exam', () => {
  const examInfo = ref({
    examId: 1,
    examName: '考试名称',
    examType: '考试类型',
    examStatus: '考试状态',
    examStartTime: '2021-01-01',
    examEndTime: '2021-01-01',
  });
  const examType = ref({
    1: '单选题',
    2: '多选题'
  });
  const currentType = ref(1);
  const currentIndex = ref(0);
  const examDetail = ref([
    {
      questionType: 1,
      questionList: [
        {
          "id": null,
          "questionType": 1,
          "gradeLevel": null,
          "subjectId": 2,
          "title": "1+1=?123",
          "items": [
            {
              "prefix": "A",
              "content": "1"
            },
            {
              "prefix": "B",
              "content": "2"
            },
            {
              "prefix": "C",
              "content": "3"
            },
            {
              "prefix": "D",
              "content": "4"
            }
          ],
          "analyze": "问小朋友",
          "correct": "B",
          "score": "",
          "difficult": 5
        },
        {
          "id": null,
          "questionType": 1,
          "gradeLevel": null,
          "subjectId": 2,
          "title": "1+1=?",
          "items": [
            {
              "prefix": "A",
              "content": "1"
            },
            {
              "prefix": "B",
              "content": "2"
            },
            {
              "prefix": "C",
              "content": "3"
            },
            {
              "prefix": "D",
              "content": "4"
            }
          ],
          "analyze": "问小朋友",
          "correct": "B",
          "score": "",
          "difficult": 5
        }
      ]
    },
    {
      questionType: 2,
      questionList: [
        {
          "id": null,
          "questionType": 1,
          "gradeLevel": null,
          "subjectId": 2,
          "title": "1+1=?",
          "items": [
            {
              "prefix": "A",
              "content": "1"
            },
            {
              "prefix": "B",
              "content": "2"
            },
            {
              "prefix": "C",
              "content": "3"
            },
            {
              "prefix": "D",
              "content": "4"
            }
          ],
          "analyze": "问小朋友",
          "correct": "B",
          "score": "",
          "difficult": 5
        },
        {
          "id": null,
          "questionType": 1,
          "gradeLevel": null,
          "subjectId": 2,
          "title": "1+1=?",
          "items": [
            {
              "prefix": "A",
              "content": "1"
            },
            {
              "prefix": "B",
              "content": "2"
            },
            {
              "prefix": "C",
              "content": "3"
            },
            {
              "prefix": "D",
              "content": "4"
            }
          ],
          "analyze": "问小朋友",
          "correct": "B",
          "score": "",
          "difficult": 5
        }
      ]
    }
  ]);
  const activeQuestion = ref(null);
  const setExamInfo = (info) => {
    examInfo.value = info;
  };
  const setExamDetail = (detail) => {
    examDetail.value = detail;
  };
  const setActiveQuestion = (detail) => {
    activeQuestion.value = detail;
  };
  return {
    examInfo
  }
    examInfo,
    examDetail,
    examType,
    activeQuestion,
    currentType,
    currentIndex,
    setExamInfo,
    setExamDetail,
    setActiveQuestion
  };
});
export default useExamStore;
src/store/modules/user.js
@@ -1,11 +1,9 @@
import { ref } from 'vue';
import { defineStore } from 'pinia';
const useUserInfoStore = defineStore('userInfo', () => {
export const useUserInfoStore = defineStore('userInfo', () => {
  const userInfo = ref('');
  return {
    userInfo
  }
});
export default useUserInfoStore;
src/views/exam/components/answer-main/answer-single/index.vue
@@ -1,13 +1,13 @@
<template>
  <div class="answer-container w-full h-full">
    <el-scrollbar>
      <ExamInfo class="mb-5"></ExamInfo>
      <ExamInfo class="mb-5" :questionIndex="currentIndex" :title="activeQuestion.title"></ExamInfo>
      <div class="answer-content">
        <div class="answer-item flex" v-for="item, index in examInfo.answerList" @click="answerClick(item)"
        <div class="answer-item flex" v-for="item, index in activeQuestion.items" @click="answerClick(item)"
          :class="answerState(item)">
          <div class="answer-icon flex flex-col justify-center items-center flex-shrink-0">{{ item.type }}</div>
          <div class="answer-text text-gray-700">{{ item.text }}</div>
          <div class="answer-icon flex flex-col justify-center items-center flex-shrink-0">{{ item.prefix }}</div>
          <div class="answer-text text-gray-700">{{ item.content }}</div>
        </div>
      </div>
@@ -17,36 +17,12 @@
<script setup>
import { ref } from 'vue';
import {storeToRefs} from 'pinia';
import ExamInfo from '@/components/ExamInfo/index.vue';
import {useExamStore} from '@/store/index.js';
const examStore = useExamStore();
const examInfo = ref({
  qId: 1,
  answerList: [
    {
      type: 'A',
      text: '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试试测试',
      isActive: false
    },
    {
      type: 'B',
      text: '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试试测试',
      isActive: false
    },
    {
      type: 'C',
      text: '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试试测试',
      isActive: false
    },
    {
      type: 'D',
      text: '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试试测试',
      isActive: false
    },
  ]
});
const activeIndex = ref(null);
const {currentIndex,activeQuestion} = storeToRefs(examStore);
const answerClick = (item) => {
  if(item) {
    resetAnswer();
@@ -61,9 +37,10 @@
}
const resetAnswer = () => {
  examInfo.value.answerList.forEach(item => item.isActive = false);
  activeQuestion.value.items.forEach(item => item.isActive = false);
}
</script>
<style lang="scss" scoped>
src/views/exam/components/answer-sheet/index.vue
@@ -1,12 +1,12 @@
<template>
  <div class="sheet-container w-full h-full">
    <el-scrollbar>
      <el-collapse v-model="activeNames" @change="handleChange">
        <template v-for="item in sheetList">
          <el-collapse-item :title="item.title" :name="item.type">
      <el-collapse v-model="activeNames">
        <template v-for="item in examDetail">
          <el-collapse-item :title="examType[item.questionType]" :name="item.questionType">
            <div class="sheet-list grid grid-cols-5 gap-4 justify-items-center">
              <div class="sheet-item cursor-pointer flex justify-center items-center" v-for="index in item.total" @click="sheetClick(item,index)" :class="itemClass(item.type, index)">
                {{ index }}
              <div class="sheet-item cursor-pointer flex justify-center items-center" v-for="question,index in item.questionList" @click="sheetClick(question,index)" :class="itemClass(item.questionType, index)">
                {{ index + 1 }}
              </div>
            </div>
          </el-collapse-item>
@@ -18,45 +18,24 @@
<script setup>
import { ref } from 'vue';
import {storeToRefs} from 'pinia';
import {useExamStore} from '@/store/index.js';
const examStore = useExamStore();
const categroy = ref(0);
const sheetIndex = ref(0);
const {examType, examDetail,currentType,currentIndex} = storeToRefs(examStore);
const itemClass = (type,index) => {
  return {
    active: categroy.value === type && sheetIndex.value === index
    active: currentType.value === type && currentIndex.value === index
  }
}
const sheetList = ref([
  {
    title: '单选题',
    type: 1,
    total: 20,
  },
  {
    title: '多选题',
    type: 2,
    total: 20,
  },
  {
    title: '判断题',
    type: 3,
    total: 20,
  },
]);
const activeNames = ref(sheetList.value.map(item => item.type));
const handleChange = () => {
};
const activeNames = ref(examDetail.value.map(item => item.questionType));
const sheetClick = (item, index) => {
  categroy.value = item.type;
  sheetIndex.value = index;
  currentType.value = item.questionType;
  currentIndex.value = index;
  examStore.setActiveQuestion(item);
}
</script>
src/views/exam/index.vue
@@ -56,7 +56,7 @@
              <div class="main-wrapper w-full grow relative my-5">
                <div class="main-content absolute top-0 bottom-0 w-full">
                  <Transition appear name="fade-transform" mode="out-in">
                    <component :is="typeComponent[currentType]" :key="questionIndex"></component>
                    <component :is="typeComponent[currentType]" :key="currentIndex"></component>
                  </Transition>
                </div>
              </div>
@@ -97,7 +97,8 @@
</template>
<script setup>
import { ref } from 'vue';
import { ref, toRefs } from 'vue';
import { storeToRefs } from 'pinia';
import { Close } from '@element-plus/icons-vue';
import AnswerTag from './components/answer-tag/index.vue';
import AnswerProgress from './components/answer-progress/index.vue';
@@ -105,23 +106,73 @@
import AnswerSingle from './components/answer-main/answer-single/index.vue';
import AnswerMultiple from './components/answer-main/answer-multiple/index.vue';
import AnswerTime from './components/answer-time/index.vue';
import { useExamStore } from '@/store/index.js';
const examStore = useExamStore();
const { currentType, currentIndex, activeQuestion, examDetail } = storeToRefs(examStore);
const typeComponent = {
  1: AnswerSingle,
  2: AnswerMultiple,
};
const currentType = ref(1);
const questionIndex = ref(0);
examStore.setActiveQuestion(examDetail.value[0].questionList[0]);
const dialogVisible = ref(false);
const prevQuestion = () => {
  questionIndex.value--;
  currentIndex.value--;
  checkList();
};
const nextQuestion = () => {
  questionIndex.value++;
  currentIndex.value++;
  checkList();
};
const checkList = () => {
  let tempIndex = 0;
  const typeQuestion = examDetail.value.find((typeItem, index) => {
    if (typeItem.questionType === currentType.value) {
      tempIndex = index;
      return typeItem;
    } else {
      return false;
    }
  });
  if (typeQuestion) {
    if (currentIndex.value >= typeQuestion.questionList.length) {
      tempIndex++;
      if(examDetail.value[tempIndex]) {
        currentType.value = examDetail.value[tempIndex].questionType;
        currentIndex.value = 0;
      } else {
        currentType.value = typeQuestion.questionType;
        currentIndex.value = typeQuestion.questionList.length - 1;
      }
    } else if (currentIndex.value < 0) {
      tempIndex--;
      if(examDetail.value[tempIndex]) {
        currentType.value = examDetail.value[tempIndex].questionType;
        currentIndex.value = examDetail.value[tempIndex].questionList.length - 1;
      } else {
        currentType.value = typeQuestion.questionType;
        currentIndex.value = 0;
      }
    }
    findQuestion(currentType.value, currentIndex.value);
  }
};
const findQuestion = (type, index) => {
  const typeQuestion = examDetail.value.find(typeItem => typeItem.questionType === type);
  if (typeQuestion) {
    const question = typeQuestion.questionList[index];
    if (question) {
      examStore.setActiveQuestion(question);
    }
  }
};
const closeClick = () => {
@@ -130,7 +181,7 @@
const confirmCancel = () => {
  dialogVisible.value = false;
}
};
</script>
<style lang="scss" scoped>