| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428 |
- <template>
- <div class="test-topic">
- <!-- 测试标题 -->
- <div class="test-title" @click="handleClick">
- <el-icon><ArrowLeftBold /></el-icon>
- {{ topicTitle }}
- </div>
- <!-- 测试内容 -->
- <div class="test-content">
- <!-- 左侧 题目 -->
- <div class="content-left">
- <div class="question-container">
- <!-- 添加题目进度显示 -->
- <div class="question-progress">
- 第 {{ currentQuestionIndex + 1 }}/{{ questions.length }} 题
- </div>
- <!-- 添加题目内容 -->
- <div class="question-content">
- <!-- 题目 -->
- <div class="question-title" v-html="questions[currentQuestionIndex]?.qcontent"></div>
- <!-- 选项 -->
- <div class="question-options">
- <el-radio-group
- v-model="selectedOption"
- size="large"
- class="radio-button-group custom-radio-group"
- >
- <el-radio-button
- v-for="option in questions[currentQuestionIndex]?.questionOptionsList || []"
- :key="option.oid"
- :label="option.oid"
- >{{ option.ovalue }}. {{ option.oname }}</el-radio-button
- >
- </el-radio-group>
- </div>
- </div>
- <!-- 添加题目导航按钮盒子 -->
- <div class="question-navigation">
- <el-button
- type="text"
- border
- class="prev-question-btn"
- @click="handlePrevQuestion"
- >上一题</el-button
- >
- <!-- 下一题按钮样式 最后一题显示为提交 -->
- <el-button
- type="primary"
- class="next-question-btn"
- @click="currentQuestionIndex === questions.length - 1 ? handleSubmit() : handleNextQuestion()"
- >{{ currentQuestionIndex === questions.length - 1 ? '提交' : '下一题' }}</el-button
- >
- </div>
- </div>
- </div>
- <!-- 右侧答题卡 -->
- <div class="content-right">
- <div class="center-box">
- <div class="box-title">答题卡</div>
- <div class="box-content">
- <div class="number-buttons">
- <el-button
- v-for="num in questions.length"
- :key="num"
- class="circle-btn"
- :class="{
- clicked: clickedNumbers.includes(num),
- current: num === currentQuestionIndex + 1
- }"
- @click="handleButtonClick(num)"
- >{{ num }}</el-button
- >
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </template>
- <script setup>
- import { ref,watch ,onMounted} from 'vue'
- import { ArrowLeftBold } from '@element-plus/icons-vue'
- import { useRouter,useRoute } from 'vue-router'
- import {QuestionTopicList, QuestionTopicSave} from '@/api/question/test.js'
- import { ElMessage } from 'element-plus'
- const router = useRouter()
- const route = useRoute()
- const selectedOption = ref(null)
- const clickedNumbers = ref([])
- // 当前题目索引
- const currentQuestionIndex = ref(0)
- const userAnswers = ref([]) // 存储用户答案
- const userQuestAnswers = ref([]) // 存储用户答案
- const handleClick = () => {
- router.push({
- path: '/evaluation',
- })
- }
- // 渲染列表标题
- const topicTitle = ref(
- route.query.title
- )
- // 添加题目数据
- const qrId = ref()
- const questResultId = ref()
- const questions = ref([])
- onMounted(()=>{
- // 获取路由参数中的id
- qrId.value = route.query.id
- if (qrId.value) {
- // 将id作为参数传递给QuestionTopicList接口
- QuestionTopicList({ qrId: qrId.value }).then(res=>{
- questResultId.value = res.data.qrResultId
- // 将接口返回的题目数据赋值给questions
- questions.value = res.data.questionnaire.questionList || []
- // 初始化用户答案数组
- userAnswers.value = new Array(questions.value.length).fill(null)
- // 初始化currentQuestionIndex
- if (questions.value.length > 0) {
- currentQuestionIndex.value = 0
- }
- }).catch(err => {
- console.error('获取题目失败:', err)
- })
- }
- })
- // 上一题按钮逻辑
- const handlePrevQuestion = () => {
- if (currentQuestionIndex.value > 0) {
- // 保存当前题目的答案
- userAnswers.value[currentQuestionIndex.value] = {
- qid: questions.value[currentQuestionIndex.value].qid,
- oid: selectedOption.value
- };
- currentQuestionIndex.value--;
- // 加载上一题的答案
- selectedOption.value = userAnswers.value[currentQuestionIndex.value]?.oid || null;
- }
- }
- // 下一题按钮逻辑
- const handleNextQuestion = () => {
- if (currentQuestionIndex.value < questions.value.length - 1) {
- // 保存当前题目的答案
- userAnswers.value[currentQuestionIndex.value] = {
- qid: questions.value[currentQuestionIndex.value].qid,
- oid: selectedOption.value
- };
- currentQuestionIndex.value++;
- // 加载下一题的答案
- selectedOption.value = userAnswers.value[currentQuestionIndex.value]?.oid || null;
- }
- }
- // 提交
- const handleSubmit = () => {
- // 保存最后一题答案
- userAnswers.value[currentQuestionIndex.value] = {
- qid: questions.value[currentQuestionIndex.value].qid,
- oid: selectedOption.value
- };
- // 检查是否所有题目都已回答
- const allAnswered = userAnswers.value.every(answer => answer?.oid !== null && answer?.oid !== undefined)
- if(!allAnswered){
- ElMessage.error('检测到有题目未完成,请回答所有题目后再提交')
- return;
- }
- // 答完全部答完跳转到提交页面
- QuestionTopicSave({
- "qrId": Number(qrId.value),
- "qrResultId": Number(questResultId.value),
- "questionList": userAnswers.value
- }).then(res=>{
- ElMessage.success('提交成功')
- router.push('/testSubmit')
- })
- }
- // 答题卡
- const handleButtonClick = (num) => {
- // 切换到对应题目
- currentQuestionIndex.value = num - 1
- // 加载该题目的答案
- selectedOption.value = userAnswers.value[currentQuestionIndex.value]?.oid || null
- }
- // 监听选项变化,自动更新答题卡状态
- watch(selectedOption, (newVal) => {
- if (newVal !== null) {
- const currentQuestionNumber = currentQuestionIndex.value + 1
- // 保存当前题目的答案
- userAnswers.value[currentQuestionIndex.value] = {
- qid: questions.value[currentQuestionIndex.value].qid,
- oid: newVal
- }
- if (!clickedNumbers.value.includes(currentQuestionNumber)) {
- clickedNumbers.value.push(currentQuestionNumber)
- }
- }
- })
- </script>
- <style scoped lang="scss">
- @use 'sass:math';
- // 定义rpx转换函数
- @function rpx($px) {
- @return math.div($px, 750) * 100vw;
- }
- .test-topic {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- display: flex;
- flex-direction: column;
- background-color: #e2ddfc;
- gap: rpx(0);
- }
- .test-title {
- width: 100%;
- height: rpx(30);
- font-size: rpx(10);
- cursor: pointer;
- color: black;
- display: flex; /* 设置flex布局 */
- align-items: center; /* 垂直居中 */
- padding-left: rpx(15); /* 添加左侧内边距 */
- gap: rpx(5); /* 设置图标和文字间距 */
- }
- .test-content {
- width: 100%;
- height: 100%;
- display: flex; /* 使用flex布局使子元素并排 */
- gap: rpx(10); /* 左右盒子间距 */
- }
- // 左侧盒子样式 题目
- .content-left {
- flex: 1.5;
- border-radius: rpx(5);
- padding: rpx(10);
- }
- .question-container {
- width: 100%;
- height: 100%;
- padding-left: rpx(40);
- box-sizing: border-box;
- position: relative; // 相对定位
- }
- /* 添加题目进度样式 */
- .question-progress {
- font-size: rpx(12);
- font-weight: bold;
- color: #9e78e7;
- text-align: left;
- }
- // 题目
- .question-content {
- // margin-top: 20px;
- ::v-deep(.el-radio-button) {
- // 添加选项选中状态样式
- &.is-active .el-radio-button__inner {
- background-color: #9e78e7;
- border-color: #9e78e7;
- color: white;
- }
- }
- }
- .question-title {
- font-size: rpx(12);
- text-align: left;
- color: black;
- margin-bottom: 15px;
- line-height: 1.5;
- }
- .question-options {
- display: flex;
- flex-direction: column;
- gap: 10px;
- }
- .radio-button-group {
- display: flex;
- flex-direction: column;
- text-align: left;
- gap: 10px;
- }
- .el-radio-button {
- width: 100%;
- margin-top: rpx(10);
- justify-content: flex-start;
- }
- .el-radio-button ::v-deep(.el-radio-button__inner) {
- width: fit-content; //按钮宽度跟随文字多少变化
- height: rpx(25);
- display: flex;
- align-items: center;
- text-align: left;
- font-size: rpx(8);
- border-radius: rpx(5);
- color: black;
- border: 1px solid white;
- background: rgb(255, 255, 255, 0.5);
- }
- // 上一题 下一题按钮
- /* 添加导航按钮样式 */
- .question-navigation {
- display: flex;
- margin-top: rpx(20); // 与题目内容保持间距
- // 绝对定位到底部
- position: absolute;
- bottom: rpx(25);
- left: rpx(40);
- right: 0;
- // 上一题按钮样式
- ::v-deep(.prev-question-btn) {
- border: 1px solid #9e78e7; // 添加边框
- color: #9e78e7; // 设置文字颜色
- font-size: rpx(8);
- background-color: transparent; // 透明背景
- &:hover {
- background-color: #9e78e7; // hover效果
- color: white;
- }
- }
- // 下一题按钮样式
- ::v-deep(.next-question-btn) {
- background-color: #9e78e7; // 更换为紫色
- border-color: #9e78e7;
- font-size: rpx(8);
- &:hover {
- background-color: #8a63d2; // hover加深颜色
- border-color: #8a63d2;
- }
- }
- }
- .question-navigation .el-button {
- width: rpx(80); // 固定按钮宽度
- height: rpx(20);
- border-radius: rpx(5);
- }
- // 右侧盒子样式 答题卡
- .content-right {
- flex: 1;
- border-radius: rpx(5);
- padding: rpx(10);
- display: flex; /* 使用flex布局 */
- flex-direction: column; /* 垂直方向排列 */
- align-items: center; /* 水平居中 */
- justify-content: center; /* 垂直居中 */
- }
- // 答题卡
- .center-box {
- width: rpx(200); /* 宽度 */
- height: 100%; /* 高度 */
- background-color: #fefefe80;
- border-radius: rpx(5);
- border: 1px solid white;
- display: flex;
- flex-direction: column; /* 垂直排列子元素 */
- padding: rpx(10);
- gap: rpx(5); /* 标题和内容间距 */
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
- }
- // 标题盒子样式
- .box-title {
- width: 100%;
- height: rpx(20);
- font-size: rpx(11);
- font-weight: bold;
- border-radius: rpx(3);
- line-height: rpx(20);
- }
- // 内容盒子样式
- .box-content {
- height: 100%;
- border-radius: rpx(3);
- padding: rpx(5);
- overflow: auto; /* 内容溢出时显示滚动条 */
- }
- // 数字按钮容器
- .number-buttons {
- display: flex;
- justify-content: flex-start; // 将center改为flex-start实现左对齐
- gap: rpx(8);
- flex-wrap: wrap; // 添加换行属性
- }
- // 圆形按钮样式
- .circle-btn {
- width: rpx(25);
- height: rpx(25);
- margin-left: 0;
- border-radius: 50%; // 圆形显示
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: rpx(10);
- background-color: transparent;
- border: 1px solid white;
- color: #909090;
- min-width: auto; // 移除Element Plus按钮默认最小宽度
- }
- .circle-btn.current {
- border: 2px solid #9e78e7;
- }
- .circle-btn:focus,
- .circle-btn:active,
- .circle-btn.clicked {
- color: white;
- background-color: #9e78e7;
- }
- .circle-btn:hover{
- border: 2px solid #9e78e7;
- }
- </style>
|