guoyu/fronted_uniapp/pages/exam/result.vue
2025-12-03 18:58:36 +08:00

242 lines
6.9 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="result-container">
<view class="result-header">
<text class="result-title">考试结果</text>
</view>
<view class="score-card" v-if="scoreData">
<view class="main-score">
<text class="score-value">{{ scoreData.obtainedScore || 0 }}</text>
<text class="score-total">/ {{ scoreData.totalScore || 0 }}</text>
</view>
<view class="score-info">
<view class="info-item">
<text class="info-label">考试名称</text>
<text class="info-value">{{ scoreData.examName || '未知' }}</text>
</view>
<view class="info-item">
<text class="info-label">用时</text>
<text class="info-value">{{ formatDuration(scoreData.duration || 0) }}</text>
</view>
<view class="info-item">
<text class="info-label">提交时间</text>
<text class="info-value">{{ formatTime(scoreData.submitTime) }}</text>
</view>
</view>
</view>
<view class="action-buttons">
<button class="btn-detail" @click="viewDetail">查看详情</button>
<button class="btn-back" @click="goBack">返回列表</button>
</view>
</view>
</template>
<script>
import { getScoreDetail } from '@/api/study/score.js'
export default {
data() {
return {
examId: null,
scoreId: null,
scoreData: null,
loading: false
}
},
onLoad(options) {
if (options.examId) {
this.examId = options.examId
}
if (options.scoreId) {
this.scoreId = options.scoreId
this.loadScoreDetail()
} else {
// 如果没有scoreId从成绩列表查找
this.findScoreByExamId()
}
},
methods: {
async findScoreByExamId() {
// 从成绩列表中找到该考试的成绩
const { getMyScores } = await import('@/api/study/score.js')
try {
const response = await getMyScores()
if (response.code === 200 && response.data) {
const scores = response.data
const score = scores.find(s => s.examId == this.examId)
if (score) {
this.scoreId = score.id
this.loadScoreDetail()
} else {
uni.showToast({
title: '未找到成绩记录',
icon: 'none'
})
setTimeout(() => {
this.goBack()
}, 1500)
}
}
} catch (error) {
console.error('查找成绩失败', error)
}
},
async loadScoreDetail() {
if (!this.scoreId) return
this.loading = true
try {
const response = await getScoreDetail(this.scoreId, this.examId)
if (response.code === 200 && response.data) {
this.scoreData = response.data
} else {
throw new Error(response.msg || '加载失败')
}
} catch (error) {
console.error('加载成绩详情失败', error)
uni.showToast({
title: error.message || '加载失败',
icon: 'none'
})
} finally {
this.loading = false
}
},
viewDetail() {
uni.navigateTo({
url: `/pages/score/detail?id=${this.scoreId}${this.examId ? `&examId=${this.examId}` : ''}`
})
},
goBack() {
uni.navigateBack({
delta: 2 // 返回两层(跳过答题页)
})
},
formatDuration(seconds) {
if (!seconds) return '0分钟'
const hours = Math.floor(seconds / 3600)
const minutes = Math.floor((seconds % 3600) / 60)
if (hours > 0) {
return `${hours}小时${minutes}分钟`
}
return `${minutes}分钟`
},
formatTime(timeStr) {
if (!timeStr) return ''
const date = new Date(timeStr)
const year = date.getFullYear()
const month = (date.getMonth() + 1).toString().padStart(2, '0')
const day = date.getDate().toString().padStart(2, '0')
const hour = date.getHours().toString().padStart(2, '0')
const minute = date.getMinutes().toString().padStart(2, '0')
return `${year}-${month}-${day} ${hour}:${minute}`
}
}
}
</script>
<style lang="scss" scoped>
.result-container {
padding: 40rpx;
background-color: #f5f5f5;
min-height: 100vh;
}
.result-header {
text-align: center;
margin-bottom: 40rpx;
.result-title {
font-size: 40rpx;
font-weight: bold;
color: #333;
}
}
.score-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 20rpx;
padding: 60rpx 40rpx;
margin-bottom: 40rpx;
text-align: center;
.main-score {
margin-bottom: 40rpx;
.score-value {
font-size: 120rpx;
font-weight: bold;
color: #fff;
line-height: 1;
}
.score-total {
font-size: 48rpx;
color: rgba(255, 255, 255, 0.8);
margin-left: 10rpx;
}
}
.score-info {
background: rgba(255, 255, 255, 0.2);
border-radius: 16rpx;
padding: 30rpx;
.info-item {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
.info-label {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.9);
}
.info-value {
font-size: 28rpx;
color: #fff;
font-weight: bold;
}
}
}
}
.action-buttons {
display: flex;
gap: 20rpx;
button {
flex: 1;
padding: 24rpx;
border-radius: 12rpx;
font-size: 28rpx;
border: none;
&.btn-detail {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #fff;
font-weight: bold;
}
&.btn-back {
background: #fff;
color: #667eea;
border: 2rpx solid #667eea;
}
}
}
</style>