Files
tra-app/src/pages/examination/index.vue
T
2025-08-08 15:33:09 +08:00

386 lines
9.3 KiB
Vue

<template>
<view class="main_div max_page">
<nav-bar :is_seat="true"></nav-bar>
<view class="nav-div">
<view class="title ellipsis-text" @click="hand_in_paper()">
{{paperData.papersName}}
</view>
<view class="back_div"></view>
</view>
<view class="countdown-and-question-number-div">
<view class="top">
<view class="countdown">
<text class="grey">答题进度</text> <text class="bold">{{questionNumber + 1}}</text><text
class="grey">/{{topicList.length}}</text>
</view>
<view class="question">
<view class="grey">剩余时间</view>
<uv-count-down :time="paperData.limitTm * 1000" format="HH:mm:ss"></uv-count-down>
</view>
</view>
<view class="progress">
<uv-line-progress :percentage="progress" :showText="false" activeColor="#FFFFFF" inactiveColor="#89B8FF"
:height="8"></uv-line-progress>
</view>
</view>
<view class="scroll_div">
<swiper class="swiper" :indicator-dots="false" @change="swiperChange" :current="questionNumber"
easing-function="linear">
<swiper-item v-for="(item,index) in topicList">
<view class="content">
<view class="expose_shadow"></view>
<scroll-view :scroll-y="true" class="scroll-Y" :show-scrollbar="false" :refresher-threshold="0">
<RadioSubject :item="item" v-if="item.qnsTyp !== 'ES'" :mode="mode">
</RadioSubject>
<CharactersSubject :item="item" v-if="item.qnsTyp === 'ES'" :mode="mode">
</CharactersSubject>
</scroll-view>
</view>
</swiper-item>
</swiper>
</view>
<view class="fixed-box font_pf">
<view class="fixed-btn-box">
<view class="sheet">
<image :src="examinationSheetIcon()" class="img"></image>
<view class="sheet_text">答题卡</view>
</view>
<view class="button_div">
<uv-button class="button" type="primary" :throttleTime="100" text="上一题" color="#E2EDFF"
custom-style="color:#0066FF;borderRadius:16rpx;height:92rpx;"
@click="button_tab(-1)"></uv-button>
<view style="width:46rpx"></view>
<uv-button class="button" type="primary" :throttleTime="100" text="下一题" color="#0066FF"
custom-style="color:#FFFFFF;borderRadius:16rpx;height:92rpx;"
@click="button_tab(1)"></uv-button>
</view>
</view>
<view class="touch-btn-div" :class="{'show':showTouchBtn}">
<TouchBtn class="talk-btns" @uploadVoice="uploadRecordNow"
@submitAnswer="submitAnswerNow" :loadingText="sendLoadingText" :isLoading="!answerIsOver"
:isDisabled="false" />
</view>
</view>
</view>
</template>
<script setup>
import RadioSubject from '@/components/examination/radio-subject.vue'
import CharactersSubject from '@/components/examination/characters-subject.vue'
import TouchBtn from '@/pages/course/components/touchBtn.vue'
import {
ref,
reactive,
computed,
onMounted,
nextTick,
getCurrentInstance
} from 'vue';
import {
examinationSheetIcon
} from '@/common/imgSvg'
import {
onLoad
} from '@dcloudio/uni-app'
import common from '@/common/common';
import {
getPageCache
} from '@/common/common';
import {
commonUploadVoiceFile
} from "@/api/common.js"
const sendLoadingText = ref('问题回答中,请在问题回答结束后重试!')
const answerIsOver = ref(true)
const examId = ref('')
const mode = ref('examination') // 考试 examination 练习practice
const paperData = reactive({
papersId: '',
limitTm: 0,
papersName: '',
}) // 试卷信息
const topicList = reactive([]) // 问题列表
const questionNumber = ref(0) // 题号
const showTouchBtn = computed(() => {
return topicList[questionNumber.value]['qnsTyp'] === 'ES'
})
// const showTouchBtn = ref(true)
const progress = computed(() => { // 计算进度百分比(保留两位小数)
const total = topicList.length;
if (total === 0) return 0;
const completed = questionNumber.value + 1;
return Math.min(Math.round((completed / total) * 10000) / 100, 100);
})
const swiperChange = (item) => {
questionNumber.value = item.detail.current
}
// 按上一题下一题
const button_tab = (num) => {
let newNumber = questionNumber.value + num;
if (newNumber < 0) {
newNumber = 0;
} else if (newNumber >= topicList.length) {
newNumber = topicList.length - 1;
}
questionNumber.value = newNumber;
}
// 发送语音
const uploadRecordNow = (voicePath) => {
//#ifdef APP-PLUS
// talkingList.value.push({
// type: 'question',
// talkingText: '',
// isLoading: true
// })
// scrollToBottomNow()
commonUploadVoiceFile(voicePath, '/traask/traAskchat/voiceTrans', {}).then(res => {
let _res = JSON.parse(res.data)
console.log('_res', _res);
if (_res.rtnCode === '0000') {
// if (!!(_res.body.transContent || '').trim()) {
// askData.value = {
// reqBatch: reqBatch.value,
// intrctWay: '02', //01-文本;02-语音;03-图片
// intrctContent: _res.body.transContent,
// bucketKey: _res.body.fileId,
// ossFileAddr: _res.body.ossFileAddr,
// talkingVoice: voicePath
// }
// sendMessage({
// "commond": 'ASK',
// "body": askData.value
// })
// } else {
// // talkingList.value.pop()
// uni.showToast({
// title: '未识别到文字!',
// icon: "none",
// duration: 1000
// });
// }
} else {}
}).catch(err => {
// talkingList.value.pop()
uni.showToast({
title: '系统异常,请联系管理员',
icon: "none",
duration: 1000
});
})
// #endif
}
// 发送文本
const submitAnswerNow = (val, cb = null) => {
}
// 初始化时检查
onLoad(() => {
const examination = getPageCache('examination')
if (!examination) {
common.navigateBack()
return
}
paperData.papersId = examination.papersId
paperData.limitTm = examination.limitTm
paperData.papersName = examination.papersName
topicList.push(...examination.qnsInfoVos.map(res => ({
...res,
my_answer: [],
backend_answer: [],
})))
});
const hand_in_paper = () => {
console.log('点击交卷', showTouchBtn.value);
showTouchBtn.value = !showTouchBtn.value
}
</script>
<style scoped lang="scss">
$bg-margin-left: 30rpx;
.fixed-box {
position: fixed;
width: 100%;
left: 0;
bottom: 0;
border-radius: 16rpx 16rpx 0px 0px;
border: 2rpx solid #E5E5E5;
background: #FFFFFF;
}
.touch-btn-div {
height: 0;
overflow: hidden;
transition: height 0.2s ease-out;
}
.touch-btn-div.show {
height: 150rpx;
}
.fixed-btn-box {
height: 154rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20rpx 20rpx 20rpx;
.sheet {
display: flex;
flex-direction: column;
align-items: center;
margin: 0 70rpx;
.img {
width: 38rpx;
height: 40rpx;
}
.sheet_text {
margin-top: 8rpx;
font-family: PingFangSC;
font-weight: 500;
font-size: 24rpx;
color: #000000;
}
}
.button_div {
flex: 1;
display: flex;
justify-content: space-between;
.button {
flex: 1;
}
}
}
.scroll-Y {
max-height: calc(100vh - var(--status-bar-height) - 70rpx - 70rpx - 40rpx - 64rpx - 68rpx - 60rpx);
min-height: calc(100vh - var(--status-bar-height) - 70rpx - 70rpx - 40rpx - 64rpx - 68rpx - 60rpx - 380rpx);
// background-color: yellow;
}
.swiper {
// 状态栏 var(--status-bar-height)
// 标题栏 70rpx
// 进度时间栏 70rpx
// 进度时间栏上下间距 40rpx = 20rpx + 20rpx
// 正文上下间距 64rpx
height: calc(100vh - var(--status-bar-height) - 70rpx - 70rpx - 40rpx - 64rpx);
// background-color: red;
}
.content {
position: relative;
margin: 32rpx $bg-margin-left;
border-radius: 16rpx;
padding: 34rpx 30rpx 34rpx 36rpx;
background-color: #fff;
.expose_shadow {
margin-left: 36rpx;
position: absolute;
bottom: -26rpx;
left: 0%;
width: calc(100% - 66rpx);
height: 28rpx;
background-color: #FFFFFF;
border-radius: 0 0 14rpx 14rpx;
opacity: 0.4;
z-index: 0;
// background-color: red;
}
}
.countdown-and-question-number-div {
margin: 20rpx $bg-margin-left;
height: 70rpx;
// background-color: red;
display: flex;
flex-direction: column;
justify-content: space-between;
z-index: 10;
.top {
display: flex;
align-items: center;
justify-content: space-between;
font-family: PingFangSC;
font-size: 26rpx;
color: #FFFFFF;
text-align: left;
font-style: normal;
}
.question {
display: flex;
align-items: center;
// background-color: red;
width: 242rpx;
color: red;
.grey {
margin-right: 8rpx;
}
:deep(.uv-count-down__text) {
color: #FFFFFF !important;
font-weight: 600;
font-size: 26rpx !important;
}
}
.grey {
color: #B6E2FF;
}
.bold {
font-weight: 600;
}
}
.nav-div {
position: relative;
.title {
// padding-top:var(--status-bar-height);
// padding: 0 30rpx;
margin: 0 calc($bg-margin-left + 70rpx);
height: 70rpx;
font-family: PingFangSC;
font-weight: 500;
font-size: 34rpx;
color: #FFFFFF;
text-align: center;
font-style: normal;
line-height: 70rpx;
}
.back_div {
position: absolute;
right: $bg-margin-left;
top: 0;
width: 70rpx;
height: 70rpx;
// background-color: red;
}
}
.main_div {
display: flex;
flex-direction: column;
background: linear-gradient(to top, #3480FF, #0066FF);
/* 确保背景占满整个视口高度 */
min-height: 100vh;
margin: 0;
}
</style>