Files
tra-app/src/pages/examination/result.vue
T
2025-08-28 16:54:52 +08:00

668 lines
15 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="main_div max_page">
<nav-bar :is_seat="true"></nav-bar>
<view class="nav-div">
<view class="title ellipsis-text">考试结算</view>
<view class="back_div" @click="common.navigateBack()">
<view class="back-icon"></view>
</view>
</view>
<scroll-view
:scroll-y="true"
@scroll="scroll"
:scroll-top="scrollTop"
class="scroll scroll-Y"
:scroll-with-animation="true"
:show-scrollbar="false"
>
<view class="information-details-div">
<view class="top">
<view class="left">
<view class="top">得分</view>
<view class="mid">
<text v-if="pass_status === 0" class="loading-pass">--</text>
<text v-if="pass_status === -1" class="no-pass">{{ result.examGrade }}</text>
<text v-if="pass_status === 1" class="pass">{{ result.examGrade }}</text>
</view>
<view class="bottom">
<text v-if="pass_status === -1">失败乃成功之母继续努力</text>
<text v-if="pass_status === 1">考的不错啊继续加油</text>
<text v-if="pass_status === 0">考试结果计算中...</text>
<image
v-if="pass_status === 1"
src="@/static/images/login/clap.png"
mode="widthFix"
style="width: 32rpx"
></image>
</view>
</view>
<view class="right">
<view class="img_div">
<image
v-if="pass_status === 1"
src="@/static/images/examination/qualified.png"
mode="aspectFit"
class="img"
></image>
<image
v-if="pass_status === -1"
src="@/static/images/examination/unqualified.png"
mode="aspectFit"
class="img"
></image>
<image
v-if="pass_status === 0"
src="@/static/images/examination/getting_in.gif"
mode="aspectFit"
class="img"
></image>
</view>
</view>
</view>
<view class="bottom">
<!-- 考试标题 -->
<view class="title-div">
<view class="title-icon">
<image
src="@/static/images/examination/examination-icon.png"
mode="widthFix"
class="img"
></image>
</view>
<view class="title ellipsis-text">考试{{ result.papersName }}</view>
</view>
<!-- 时间和考试按钮 -->
<view class="time-and-exam-button">
<view class="time-icon">
<image src="@/static/images/examination/duration-icon.png" mode="widthFix" class="img"></image>
</view>
<view class="time">
<!-- 12 15 -->
时长{{ result.examLenTm }}
</view>
<view class="fl1"></view>
<view class="examination" @click="goExamRanking" v-if="result.mode === 'examination'">
<view>考试排行榜</view>
<view class="back-icon"></view>
</view>
</view>
</view>
</view>
<view class="main-div">
<view class="sheet_table_div" v-if="pass_status !== 0 && topicList.length > 0">
<swiper
:indicator-dots="false"
class="sheet_swiper"
:style="{ height: topicList.length > 5 ? '230rpx' : '115rpx' }"
:current="sheet_swiper_index"
@change="sheet_swiper_change"
>
<!-- 循环渲染分组后的数组 -->
<swiper-item v-for="(group, groupIndex) in groupedTopicList" :key="groupIndex">
<uv-grid :col="5" class="sheet_table" @click="sheet_click">
<uv-grid-item v-for="(item, index) in group" :key="index">
<view class="circle">
{{ groupIndex * 10 + index + 1 }}
</view>
</uv-grid-item>
</uv-grid>
</swiper-item>
</swiper>
<view class="swiper-dots"></view>
</view>
<!-- 获取答题结果时候的图片 -->
<view class="loading-pass-image-div" v-if="pass_status === 0">
<image src="@/static/images/examination/getting_robot.png" mode="widthFix" class="img"></image>
<view class="tip">你的等待会有更精确的结果要耐心哦~</view>
</view>
<view class="" :id="'id_' + index" :class="getStatusClass(index)" v-for="(item, index) in topicList">
<Subject :item="item" mode="settlement" :clearResult="false" :isPreview="true"></Subject>
</view>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { onLoad, onUnload } from '@dcloudio/uni-app';
import { ref, reactive, computed, onMounted, nextTick, getCurrentInstance } from 'vue';
import { queryPaperExamScore } from '@/api/examination.js';
import Subject from '@/components/examination/subject.vue';
import common from '@/common/common';
const pass_status = ref(0);
const sheet_swiper_index = ref(0);
const result = reactive({
crsId: '',
execId: '',
papersId: '',
mode: '',
papersName: '',
examLenTm: '',
examGrade: ''
});
const sheet_swiper_change = (event) => {
sheet_swiper_index.value = event.detail.current;
};
const topicList = reactive([]);
// 答题卡计算属性
const groupedTopicList = computed(() => {
if (!topicList || topicList.length === 0) {
return [];
}
const groups = [];
for (let i = 0; i < topicList.length; i += 10) {
// 从索引i开始,截取最多10个元素
const group = topicList.slice(i, i + 10);
groups.push(group);
}
return groups;
});
const scrollTop = ref(0);
// 答题卡点击
const sheet_click = (index) => {
scrollTop.value = index * 200;
};
const scroll = (event) => {
};
// 跳转到去考试页面
const goExamRanking = () => {
// 首先判断是课程跳入还是考试中心跳入
if(result.crsId !== '') {
common.navigateTo('/pages/examRanking/index?crsId=' + result.crsId)
} else {
common.navigateTo('/pages/examRanking/index?papersId=' + result.papersId)
}
}
const getStatusClass = (index) => {
const remainder = index % 3;
if (remainder === 0) return 'in_progress';
if (remainder === 1) return 'completed';
return 'expired';
};
const animationfinish = (event) => {
console.log('event', event);
};
// 定义请求计数器和定时器引用
const requestCount = ref(0);
const timerId = ref(null);
const get_result = () => {
// 重置计数器(首次调用时)
if (requestCount.value === 0) {
requestCount.value = 0;
}
// 检查是否已达到最大请求次数
if (requestCount.value >= 15) {
console.log('已达到最大请求次数(15次),停止请求');
return;
}
timerId.value = setTimeout(() => {
// 每次请求前计数器+1
requestCount.value++;
queryPaperExamScore({
execId: result.execId
}).then(({ body }) => {
console.log(`第${requestCount.value}次请求返回`, body);
if (body.isWait === 'Y') {
// 未完成且未达上限,继续请求
if (requestCount.value < 15) {
get_result();
} else {
console.log('已达到最大请求次数,停止等待');
}
} else if (body.isWait === 'N') {
// 完成请求,处理结果
pass_status.value = body.examResult === 'P' ? 1 : -1;
result.examGrade = body.examGrade;
topicList.push(...body.qnsInfoVo);
}
}).catch(err => {
console.error('请求失败', err);
// 请求失败也计入次数,避免无限重试
if (requestCount.value < 15) {
get_result();
}
});
}, 2000);
};
// 初始化时检查
onLoad((e) => {
result.crsId = e.crsId;
result.execId = e.execId;
result.papersName = e.papersName;
result.examLenTm = e.examLenTm;
result.mode = e.mode || '';
result.papersId = e.papersId;
get_result();
});
// 页面卸载时清除定时器,终止请求
onUnload(() => {
if (timerId.value) {
clearTimeout(timerId.value);
timerId.value = null;
}
});
</script>
<style scoped lang="scss">
$bg-margin-left: 30rpx;
.scroll-Y {
// max-height: calc(100vh - var(--status-bar-height) - 70rpx - 70rpx - 40rpx - 64rpx - 68rpx - 60rpx);
height: calc(100vh - var(--status-bar-height) - 70rpx - 10rpx);
// background-color: red;
}
.item {
border-radius: 16rpx;
margin: 18rpx 0;
padding: 22rpx 30rpx 34rpx 36rpx;
background-color: #fff;
display: flex;
flex-direction: column;
.top {
display: flex;
align-items: center;
.type {
width: 108rpx;
height: 46rpx;
background: #267eff;
border-radius: 8rpx;
font-family: PingFangSC;
font-weight: 500;
font-size: 25rpx;
color: #ffffff;
text-align: center;
line-height: 46rpx;
}
.score {
margin-left: 24rpx;
font-family: ArialMT;
font-size: 30rpx;
color: #333333;
text-align: left;
}
.right {
display: flex;
align-items: center;
.right_text {
font-family: PingFangSC;
font-weight: 600;
font-size: 28rpx;
color: #333;
line-height: 40rpx;
text-align: left;
font-style: normal;
}
}
}
.text {
font-family: PingFangSC;
font-weight: 500;
font-size: 30rpx;
color: #333333;
line-height: 48rpx;
text-align: left;
font-style: normal;
margin-top: 20rpx;
}
}
.sticky {
}
.sheet_table_div_fixed {
position: absolute;
top: calc(var(--status-bar-height) + 70rpx);
left: 0;
z-index: 600;
height: 230rpx;
width: calc(100% - 56rpx);
margin: 0 28rpx 0 28rpx;
background-color: #fff;
// opacity: .5;
}
.sheet_table_div {
position: sticky;
left: 0;
top: 0;
width: 100%;
z-index: 600;
background-color: #fff;
}
.sheet_swiper {
// max-height: 230rpx;
}
.swiper-dots {
height: 20rpx;
}
.sheet_table {
padding: 0 12rpx;
width: 100%;
display: flex;
.circle {
width: 78rpx;
height: 78rpx;
border-radius: 100%;
display: flex;
align-items: center;
justify-content: center;
border: 2rpx solid #e5e5e5;
margin: 20rpx;
}
.current {
background-color: rgba(0, 102, 255, 0.6);
border-color: #0066ff;
color: #ffffff;
}
.completed {
// 已完成
background-color: rgba(0, 102, 255, 0.1);
border-color: #0066ff;
color: #0066ff;
}
.mark,
.completed.mark {
background-color: rgba(232, 181, 49, 0.1);
color: #e8b531;
border-color: #e8b531;
}
.current.mark {
// 已完成
background-color: rgba(0, 102, 255, 0.6);
color: #ffffff;
border-color: #e8b531;
}
}
// 主内容框
.main-div {
display: flex;
flex-direction: column;
padding: 34rpx 0 30rpx 0;
margin: 30rpx 28rpx 20rpx 28rpx;
border-radius: 16rpx;
position: relative;
background-color: #fff;
// min-height: calc(100vh - var(--status-bar-height) - 70rpx - 380rpx - 100rpx);
.main-div-title {
width: 100%;
height: 44rpx;
font-family: PingFangSC;
font-weight: 700;
font-size: 33rpx;
color: #000000;
line-height: 44rpx;
text-align: left;
font-style: normal;
margin-left: 48rpx;
}
.loading-pass-image-div {
display: flex;
flex-direction: column;
align-items: center;
padding-top: 80rpx;
padding-bottom: 100rpx;
.img {
// background-color: red;
width: 52vw;
margin-left: -100rpx;
}
.tip {
font-family: PingFangSC;
font-weight: 400;
font-size: 30rpx;
color: #666666;
line-height: 40rpx;
text-align: center;
font-style: normal;
}
}
}
// 信息框
.information-details-div {
display: flex;
flex-direction: column;
padding: 34rpx 20rpx 30rpx 48rpx;
margin: 44rpx 28rpx 0 28rpx;
border-radius: 16rpx;
position: relative;
background-color: #fff;
opacity: 0.8;
box-shadow: 2rpx -2rpx 2rpx #fff;
& > .top {
display: flex;
justify-content: space-between;
& > .left {
display: flex;
flex-direction: column;
justify-content: space-between;
& > .top {
font-family: PingFangSC;
font-weight: 700;
font-size: 34rpx;
color: #000000;
line-height: 34rpx;
text-align: left;
font-style: normal;
}
& > .mid {
font-weight: 700;
font-size: 66rpx;
line-height: 66rpx;
text-align: left;
font-style: normal;
height: 100rpx;
// margin-top: 34rpx;
// margin-bottom: 30rpx;
}
& > .bottom {
display: flex;
align-items: center;
font-family: PingFangSC;
font-weight: 400;
font-size: 24rpx;
color: #999999;
line-height: 24rpx;
text-align: left;
font-style: normal;
}
}
& > .right {
margin-left: 20rpx;
.img_div {
.img {
width: 270rpx;
height: 190rpx;
}
}
}
}
& > .bottom {
font-family: PingFangSC;
font-weight: 400;
font-size: 26rpx;
color: #666666;
line-height: 26rpx;
text-align: left;
font-style: normal;
margin-top: 26rpx;
.title-icon,
.time-icon {
display: flex;
align-items: center;
padding-right: 12rpx;
.img {
width: 26rpx;
}
}
.title-div {
display: flex;
align-items: center;
padding-bottom: 24rpx;
}
.time-and-exam-button {
display: flex;
align-items: center;
padding-right: 12rpx;
.examination {
display: flex;
align-items: center;
color: #0066ff;
.back-icon {
position: relative;
width: 40rpx;
height: 40rpx;
cursor: pointer;
}
.back-icon::before,
.back-icon::after {
content: '';
position: absolute;
transition: all 0.3s ease;
}
.back-icon::after {
top: 25%;
left: 25%;
width: 40%;
height: 40%;
border-top: 4rpx solid #0066ff;
border-left: 4rpx solid #0066ff;
transform: rotate(135deg);
}
}
}
}
.loading-pass {
color: #0066ff;
font-family: DINAlternate, DINAlternate;
font-weight: bold;
font-size: 65rpx;
color: #0066ff;
letter-spacing: 12rpx;
}
.no-pass {
color: #d70c18;
}
.pass {
color: #0066ff;
}
}
.nav-div {
position: relative;
.title {
height: 70rpx;
font-family: PingFangSC;
font-weight: 500;
font-size: 34rpx;
color: #000000;
line-height: 70rpx;
text-align: center;
font-style: normal;
}
.back_div {
margin-right: 10rpx;
position: absolute;
left: 25rpx;
top: 0;
padding: 15rpx;
.back-icon {
position: relative;
width: 40rpx;
height: 40rpx;
cursor: pointer;
}
.back-icon::before,
.back-icon::after {
content: '';
position: absolute;
transition: all 0.3s ease;
}
.back-icon::after {
top: 25%;
left: 25%;
width: 40%;
height: 40%;
border-top: 4rpx solid #000;
border-left: 4rpx solid #000;
transform: rotate(-45deg);
}
}
}
.main_div {
display: flex;
flex-direction: column;
background-color: #f0f5f9;
/* 添加30度角的斜向上渐变,高度限制为400px */
background-image: linear-gradient(30deg, #f0f5f9, #ebf1ff);
/* 渐变背景高度400px,宽度充满容器 */
background-size: 100% 600rpx;
/* 防止渐变背景重复 */
background-repeat: no-repeat;
min-height: 100vh;
margin: 0;
overflow: hidden;
position: relative;
}
</style>