242 lines
6.9 KiB
Vue
242 lines
6.9 KiB
Vue
<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>
|
||
|