guoyu/fronted_uniapp/pages/exam/result.vue

242 lines
6.9 KiB
Vue
Raw Normal View History

2025-12-03 18:58:36 +08:00
<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>