Some checks failed
continuous-integration/drone/push Build is failing
- Add new assessment status 7 ("需重测") for cases where all scores are equal
- Create AllScoresEqualException to handle scenarios where 8 intelligences or 40 ability dimensions have identical scores
- Implement CheckAllScoresEqual validation in ReportGenerationService to detect and prevent invalid report generation
- Add UpdateRecordStatusToRetestAsync method in ReportQueueConsumer to handle retest status updates
- Update admin UI status tag mapping to display retest status with warning indicator
- Add user-friendly message for retest status in AssessmentService
- Update status description mappings across services to include new retest status
- Prevent PDF generation when all scores are equal, prompting users to retake the assessment
315 lines
6.6 KiB
Vue
315 lines
6.6 KiB
Vue
<script setup>
|
||
/**
|
||
* 测评生成中页面
|
||
*
|
||
* 功能:
|
||
* - 显示加载动画
|
||
* - 显示提示文字
|
||
* - 轮询查询报告生成状态(3秒间隔)
|
||
* - 生成完成自动跳转结果页
|
||
* - Status=7 需重测:显示提示和重新测试按钮
|
||
*/
|
||
|
||
import { ref, onMounted, onUnmounted } from 'vue'
|
||
import { onLoad } from '@dcloudio/uni-app'
|
||
import { useUserStore } from '@/store/user.js'
|
||
import { getResultStatus } from '@/api/assessment.js'
|
||
import Navbar from '@/components/Navbar/index.vue'
|
||
|
||
const userStore = useUserStore()
|
||
|
||
// 页面参数
|
||
const recordId = ref('')
|
||
const typeId = ref('')
|
||
|
||
// 轮询定时器
|
||
let pollTimer = null
|
||
|
||
// 轮询间隔(毫秒)
|
||
const POLL_INTERVAL = 3000
|
||
|
||
// 最大轮询次数(防止无限轮询)
|
||
const MAX_POLL_COUNT = 100
|
||
|
||
// 当前轮询次数
|
||
const pollCount = ref(0)
|
||
|
||
// 是否需要重新测评(Status=7)
|
||
const needRetest = ref(false)
|
||
const retestMessage = ref('')
|
||
|
||
/**
|
||
* 开始轮询查询状态
|
||
*/
|
||
function startPolling() {
|
||
// 清除已有定时器
|
||
stopPolling()
|
||
|
||
// 立即查询一次
|
||
checkStatus()
|
||
|
||
// 设置轮询定时器
|
||
pollTimer = setInterval(() => {
|
||
checkStatus()
|
||
}, POLL_INTERVAL)
|
||
}
|
||
|
||
/**
|
||
* 停止轮询
|
||
*/
|
||
function stopPolling() {
|
||
if (pollTimer) {
|
||
clearInterval(pollTimer)
|
||
pollTimer = null
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 查询报告生成状态
|
||
*/
|
||
async function checkStatus() {
|
||
if (!recordId.value) {
|
||
console.error('缺少测评记录ID')
|
||
return
|
||
}
|
||
|
||
// 检查轮询次数
|
||
pollCount.value++
|
||
if (pollCount.value > MAX_POLL_COUNT) {
|
||
stopPolling()
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '报告生成时间较长,请稍后在"往期测评"中查看',
|
||
showCancel: false,
|
||
success: () => {
|
||
uni.switchTab({
|
||
url: '/pages/mine/index'
|
||
})
|
||
}
|
||
})
|
||
return
|
||
}
|
||
|
||
try {
|
||
const res = await getResultStatus(recordId.value)
|
||
|
||
if (res && res.code === 0 && res.data) {
|
||
const status = res.data.status
|
||
|
||
// 状态:3-生成中 4-已完成 5-失败 7-需重测
|
||
if (status === 4) {
|
||
// 生成完成,跳转结果页
|
||
stopPolling()
|
||
|
||
// 携带 reportUrl 参数
|
||
const reportUrl = res.data.reportUrl || ''
|
||
uni.redirectTo({
|
||
url: `/pages/assessment/result/index?recordId=${recordId.value}&reportUrl=${encodeURIComponent(reportUrl)}`
|
||
})
|
||
} else if (status === 7) {
|
||
// 需重测:停止轮询,显示提示和重新测试按钮
|
||
stopPolling()
|
||
needRetest.value = true
|
||
retestMessage.value = res.data.message || '分析得出多个智能处于同一梯队,我们需要更细致的分析维度,接下来请您重新进行测评'
|
||
} else if (status === 5) {
|
||
// 生成失败
|
||
stopPolling()
|
||
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: res.data.message || '报告生成失败,请联系客服',
|
||
showCancel: false,
|
||
success: () => {
|
||
uni.switchTab({
|
||
url: '/pages/index/index'
|
||
})
|
||
}
|
||
})
|
||
}
|
||
// status === 3 或 6 继续轮询
|
||
}
|
||
} catch (error) {
|
||
console.error('查询状态失败:', error)
|
||
// 网络错误不停止轮询,继续尝试
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 重新测试
|
||
*/
|
||
function handleRetest() {
|
||
// 跳转到测评首页重新开始
|
||
if (typeId.value) {
|
||
uni.redirectTo({
|
||
url: `/pages/assessment/info/index?typeId=${typeId.value}`
|
||
})
|
||
} else {
|
||
uni.switchTab({
|
||
url: '/pages/index/index'
|
||
})
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 页面加载
|
||
*/
|
||
onLoad((options) => {
|
||
recordId.value = options.recordId || ''
|
||
typeId.value = options.typeId || ''
|
||
|
||
// 恢复用户登录状态
|
||
userStore.restoreFromStorage()
|
||
|
||
// 开始轮询
|
||
startPolling()
|
||
})
|
||
|
||
/**
|
||
* 页面卸载时清理定时器
|
||
*/
|
||
onUnmounted(() => {
|
||
stopPolling()
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<view class="assessment-loading-page">
|
||
<!-- 导航栏 -->
|
||
<Navbar title="多元智能测评" :showBack="true" />
|
||
|
||
<!-- 需重测提示 -->
|
||
<view v-if="needRetest" class="retest-content">
|
||
<image class="retest-image" src="/static/cepingzhong.png" mode="aspectFit" />
|
||
|
||
<view class="retest-text">
|
||
<text class="retest-title">{{ retestMessage }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 加载内容区域 -->
|
||
<view v-else class="loading-content">
|
||
<!-- 加载图片 -->
|
||
<image class="loading-image" src="/static/cepingzhong.png" mode="aspectFit" />
|
||
|
||
<!-- 提示文字 -->
|
||
<view class="loading-text">
|
||
<text class="loading-title">测评生成中,请耐心等待</text>
|
||
<text class="loading-tip">可在往期测评中查看测评结果</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 重新测试按钮 -->
|
||
<view v-if="needRetest" class="bottom-action">
|
||
<view class="retest-btn" @click="handleRetest">
|
||
<text>重新测试</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
|
||
<style lang="scss" scoped>
|
||
@import '@/styles/variables.scss';
|
||
|
||
.assessment-loading-page {
|
||
min-height: 100vh;
|
||
background-color: $bg-white;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.loading-content {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-height: calc(100vh - 200rpx);
|
||
padding: $spacing-xl;
|
||
}
|
||
|
||
// 加载图片
|
||
.loading-image {
|
||
width: 360rpx;
|
||
height: 360rpx;
|
||
margin-bottom: $spacing-xl;
|
||
}
|
||
|
||
// 提示文字
|
||
.loading-text {
|
||
text-align: center;
|
||
}
|
||
|
||
.loading-title {
|
||
display: block;
|
||
font-size: $font-size-lg;
|
||
color: $text-secondary;
|
||
margin-bottom: $spacing-sm;
|
||
}
|
||
|
||
.loading-tip {
|
||
display: block;
|
||
font-size: $font-size-md;
|
||
color: $text-placeholder;
|
||
}
|
||
|
||
// 需重测内容
|
||
.retest-content {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: $spacing-xl 64rpx;
|
||
}
|
||
|
||
.retest-image {
|
||
width: 360rpx;
|
||
height: 360rpx;
|
||
margin-bottom: $spacing-xl;
|
||
}
|
||
|
||
.retest-text {
|
||
text-align: center;
|
||
}
|
||
|
||
.retest-title {
|
||
display: block;
|
||
font-size: $font-size-lg;
|
||
color: $text-secondary;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
// 底部操作栏
|
||
.bottom-action {
|
||
position: fixed;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
padding: $spacing-lg $spacing-xl;
|
||
padding-bottom: calc(#{$spacing-lg} + env(safe-area-inset-bottom));
|
||
background-color: transparent;
|
||
z-index: 100;
|
||
}
|
||
|
||
// 重新测试按钮
|
||
.retest-btn {
|
||
width: 100%;
|
||
height: 88rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: linear-gradient(135deg, #FF8A6B 0%, #FF6B6B 100%);
|
||
border-radius: $border-radius-round;
|
||
|
||
text {
|
||
font-size: $font-size-lg;
|
||
color: $text-white;
|
||
font-weight: $font-weight-medium;
|
||
}
|
||
|
||
&:active {
|
||
opacity: 0.85;
|
||
}
|
||
}
|
||
</style>
|