You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
405 lines
11 KiB
405 lines
11 KiB
10 months ago
|
<template>
|
||
|
<BaseContainer>
|
||
|
<NavBar title="练习结果" />
|
||
|
<view class="question-result-page" v-if="result.title">
|
||
|
<view class="head">
|
||
|
<view class="header">
|
||
|
<view class="avatar"><img :src="userInfo.avatar"></view>
|
||
|
<view class="nickname">{{ userInfo.nickname }}</view>
|
||
|
<view class="circle-container">
|
||
|
<canvas canvas-id="circle" class="my-canvas"></canvas>
|
||
|
</view>
|
||
|
<view class="title">{{ result.title }}</view>
|
||
|
<view v-if="result.is_score" class="score">
|
||
|
<view class="item">
|
||
|
<view>
|
||
|
<image :src="getImgPath('/wap/first/zsff/images/result01.png')" />
|
||
|
<text>本次得分</text>
|
||
|
</view>
|
||
|
<view>{{ result.score }}</view>
|
||
|
</view>
|
||
|
<view class="item" v-if="result.grade">
|
||
|
<view>
|
||
|
<image :src="getImgPath('/wap/first/zsff/images/result02.png')" />
|
||
|
<text>评分标准</text>
|
||
|
</view>
|
||
|
<view>{{ result.grade }}</view>
|
||
|
</view>
|
||
|
</view>
|
||
|
<view class="basic">
|
||
|
<view class="item">
|
||
|
<view>题目数</view>
|
||
|
<view class="value">{{ result.test_paper_question.length }}</view>
|
||
|
</view>
|
||
|
<view class="item">
|
||
|
<view>错题数</view>
|
||
|
<view class="value">{{ result.wrong_question }}</view>
|
||
|
</view>
|
||
|
<view class="item">
|
||
|
<view>未答数</view>
|
||
|
<view class="value">{{ result.not_questions }}</view>
|
||
|
</view>
|
||
|
<view class="item">
|
||
|
<view>本次用时</view>
|
||
|
<view class="value">{{ result.duration_time }}</view>
|
||
|
</view>
|
||
|
</view>
|
||
|
</view>
|
||
|
</view>
|
||
|
<view class="result">
|
||
|
<view class="result-hd">
|
||
|
<view>答题情况</view>
|
||
|
<view class="list">
|
||
|
<view class="item"><text></text><text>正确</text></view>
|
||
|
<view class="item"><text></text><text>错误</text></view>
|
||
|
<view class="item"><text></text><text>未答</text></view>
|
||
|
</view>
|
||
|
</view>
|
||
|
<view class="result-bd">
|
||
|
<view v-for="(item, index) in result.test_paper_question"
|
||
|
:class="{ no: item.is_correct === 1, ok: item.is_correct === 2 }">{{ index + 1 }}</view>
|
||
|
</view>
|
||
|
<view v-if="!footerHidden" class="result-ft">
|
||
|
<navigator :url="`/pages/topic/question_sheet?is_analysis=1&test_id=${test_id}&record_id=${result.id}`">查看解析
|
||
|
</navigator>
|
||
|
<navigator open-type="redirect" :url="`/pages/special/question_index?id=${test_id}`">再考一次</navigator>
|
||
|
</view>
|
||
|
</view>
|
||
|
<view :class="{ mask: imgSrc }" @touchmove.prevent @click="imgSrc = ''"></view>
|
||
|
<image v-if="imgSrc" :src="imgSrc" class="certificate-image" />
|
||
|
</view>
|
||
|
</BaseContainer>
|
||
|
</template>
|
||
|
|
||
|
<script>
|
||
|
import {
|
||
|
getCertificateInfo,
|
||
|
getExaminationResult,
|
||
|
getInspect,
|
||
|
getTheCertificate,
|
||
|
} from "@/api/topic";
|
||
|
import {
|
||
|
getUserBaseData,
|
||
|
} from "@/api/user";
|
||
|
export default {
|
||
|
data() {
|
||
|
return {
|
||
|
test_id: 0,
|
||
|
result: {
|
||
|
title: "--",
|
||
|
score: 0,
|
||
|
grade: "--",
|
||
|
test_paper_question: [],
|
||
|
wrong_question: 0,
|
||
|
duration_time: "00:00:00",
|
||
|
},
|
||
|
fill: { gradient: ["rgba(44, 142, 255, 1)", "rgba(44, 142, 255, 0.05)"] },
|
||
|
footerHidden: false,
|
||
|
imgSrc: "",
|
||
|
userInfo: {}
|
||
|
};
|
||
|
},
|
||
|
onLoad({ test_id, from }) {
|
||
|
this.test_id = test_id;
|
||
|
this.footerHidden = from === "question_user";
|
||
|
|
||
|
this.$util.removeStorage("exam_time");
|
||
|
this.getUserBaseData();
|
||
|
|
||
|
},
|
||
|
mounted() {
|
||
|
this.getResult();
|
||
|
},
|
||
|
methods: {
|
||
|
async getUserBaseData() {
|
||
|
try {
|
||
|
const { data } = await getUserBaseData();
|
||
|
const {
|
||
|
userInfo
|
||
|
} = data;
|
||
|
Object.assign(this, {
|
||
|
userInfo
|
||
|
});
|
||
|
} catch (error) { }
|
||
|
},
|
||
|
renderCircle() {
|
||
|
const { screenWidth } = this.$util.getSystemInfo();
|
||
|
|
||
|
const ctx = uni.createCanvasContext("circle");
|
||
|
|
||
|
const maxValue = this.result.accuracy;
|
||
|
let value = 0;
|
||
|
|
||
|
const render = () => {
|
||
|
ctx.clearRect(0, 0, screenWidth, 160);
|
||
|
|
||
|
let text = parseInt(value) + "%";
|
||
|
|
||
|
ctx.arc(screenWidth / 2, 80, 70, 0, 2 * Math.PI);
|
||
|
ctx.setFillStyle("rgba(213, 224, 236, 0.6)");
|
||
|
ctx.fill();
|
||
|
|
||
|
ctx.beginPath();
|
||
|
ctx.arc(
|
||
|
screenWidth / 2,
|
||
|
80,
|
||
|
70,
|
||
|
0,
|
||
|
2 * Math.PI * (maxValue / 100) * (value / maxValue)
|
||
|
);
|
||
|
ctx.setFillStyle("#2c8eff");
|
||
|
ctx.fill();
|
||
|
|
||
|
ctx.beginPath();
|
||
|
ctx.arc(screenWidth / 2, 80, 64, 0, 2 * Math.PI);
|
||
|
ctx.setFillStyle("#ffffff");
|
||
|
ctx.fill();
|
||
|
|
||
|
ctx.font =
|
||
|
'32px "PingFang SC", "STHeitiSC-Light", "Helvetica-Light", arial, sans-serif, "Droid Sans Fallback"';
|
||
|
ctx.setFillStyle("#2c8eff");
|
||
|
ctx.setTextBaseline("middle");
|
||
|
let textWidth = ctx.measureText(text);
|
||
|
ctx.fillText(text, screenWidth / 2 - textWidth.width / 2, 80);
|
||
|
|
||
|
ctx.font =
|
||
|
'11px "PingFang SC", "STHeitiSC-Light", "Helvetica-Light", arial, sans-serif, "Droid Sans Fallback"';
|
||
|
ctx.setFillStyle("#999999");
|
||
|
ctx.setTextBaseline("middle");
|
||
|
text = "正确率";
|
||
|
textWidth = ctx.measureText(text);
|
||
|
ctx.fillText(text, screenWidth / 2 - textWidth.width / 2, 80 + 32);
|
||
|
|
||
|
ctx.draw();
|
||
|
};
|
||
|
|
||
|
// #ifndef MP
|
||
|
/* const task = () => {
|
||
|
render();
|
||
|
if (value < maxValue) {
|
||
|
value += 2;
|
||
|
window.requestAnimationFrame(task);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
window.requestAnimationFrame(task); */
|
||
|
// #endif
|
||
|
|
||
|
|
||
|
const flag = setInterval(() => {
|
||
|
render();
|
||
|
if (value < maxValue) {
|
||
|
value += 2;
|
||
|
} else {
|
||
|
clearInterval(flag);
|
||
|
}
|
||
|
}, 1000 / 60);
|
||
|
|
||
|
},
|
||
|
getResult() {
|
||
|
getExaminationResult({
|
||
|
test_id: this.test_id,
|
||
|
type: 2,
|
||
|
})
|
||
|
.then(({ data: result }) => {
|
||
|
let questions = result.test_paper_question;
|
||
|
|
||
|
let duration = result.duration;
|
||
|
let hours = Math.floor(duration / 3600000);
|
||
|
let minutes = Math.floor((duration - hours * 3600000) / 60000);
|
||
|
let seconds = Math.floor((duration - hours * 3600000 - minutes * 60000) / 1000);
|
||
|
if (hours < 10) {
|
||
|
hours = "0" + hours;
|
||
|
}
|
||
|
if (minutes < 10) {
|
||
|
minutes = "0" + minutes;
|
||
|
}
|
||
|
if (seconds < 10) {
|
||
|
seconds = "0" + seconds;
|
||
|
}
|
||
|
result.duration_time = hours + ":" + minutes + ":" + seconds;
|
||
|
|
||
|
for (let i = questions.length; i--;) {
|
||
|
if (!Array.isArray(questions[i].userAnswer)) {
|
||
|
Object.assign(questions[i], questions[i].userAnswer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.result = result;
|
||
|
this.renderCircle();
|
||
|
this.getInspect();
|
||
|
})
|
||
|
.catch((err) => {
|
||
|
console.log(err);
|
||
|
this.$util.showMsg(err);
|
||
|
uni.redirectTo({
|
||
|
url: "/pages/topic/question_user",
|
||
|
});
|
||
|
});
|
||
|
},
|
||
|
getInspect() {
|
||
|
getInspect(this.test_id).then(({ code }) => {
|
||
|
if (code === 200) {
|
||
|
uni.showModal({
|
||
|
title: "提示",
|
||
|
content: "恭喜您已达到证书发放标准\n是否领取?",
|
||
|
okText: "领取",
|
||
|
success: ({ confirm }) => {
|
||
|
if (!confirm) return;
|
||
|
this.getCertificate();
|
||
|
},
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
// 领取证书
|
||
|
getCertificate() {
|
||
|
getTheCertificate(this.test_id).then(({ msg }) => {
|
||
|
this.$util.showMsg("领取成功\n证书正在生成...");
|
||
|
this.getCertificateInfo(msg);
|
||
|
});
|
||
|
},
|
||
|
getCertificateInfo(id) {
|
||
|
getCertificateInfo({
|
||
|
id: id,
|
||
|
obtain: 2,
|
||
|
}).then(({ data }) => {
|
||
|
this.createCertificate(data);
|
||
|
});
|
||
|
},
|
||
|
// 加载图片
|
||
|
loadImage: function (path) {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
var image = new Image();
|
||
|
image.crossOrigin = "anonymous";
|
||
|
image.onload = function () {
|
||
|
resolve(image);
|
||
|
};
|
||
|
image.onerror = function () {
|
||
|
reject("error-image");
|
||
|
};
|
||
|
image.src = path + "?" + new Date().getTime();
|
||
|
});
|
||
|
},
|
||
|
// 生成证书图片
|
||
|
createCertificate: function (certificate) {
|
||
|
$h.loadFFF();
|
||
|
Promise.all([
|
||
|
this.loadImage(certificate.certificate.background),
|
||
|
this.loadImage(certificate.certificate.qr_code),
|
||
|
])
|
||
|
.then(function (images) {
|
||
|
var canvas = document.createElement("canvas");
|
||
|
var context = canvas.getContext("2d");
|
||
|
|
||
|
canvas.width = images[0].width;
|
||
|
canvas.height = images[0].height;
|
||
|
|
||
|
context.drawImage(images[0], 0, 0);
|
||
|
context.drawImage(images[1], 220, 557, 160, 160);
|
||
|
|
||
|
context.fillStyle = "rgba(255, 255, 255, 1)";
|
||
|
context.fillRect(220, 724, 160, 36);
|
||
|
|
||
|
context.font = "20px sans-serif";
|
||
|
context.textAlign = "center";
|
||
|
context.fillStyle = "#666666";
|
||
|
context.fillText("长按二维码查看", 300, 748);
|
||
|
|
||
|
context.font = "bold 34px sans-serif";
|
||
|
context.fillStyle = "#29466D";
|
||
|
context.fillText(certificate.nickname, 300, 296);
|
||
|
|
||
|
context.font = "24px sans-serif";
|
||
|
context.fillText(
|
||
|
"颁发时间:" + moment(certificate.add_time * 1000).format("YYYY.MM.DD"),
|
||
|
300,
|
||
|
481
|
||
|
);
|
||
|
|
||
|
context.font = "28px sans-serif";
|
||
|
context.textAlign = "start";
|
||
|
context.fillStyle = "#333333";
|
||
|
|
||
|
for (var i = Math.ceil(certificate.certificate.explain.length % 16); i--;) {
|
||
|
context.fillText(
|
||
|
certificate.certificate.explain.substr(i * 16, 16),
|
||
|
83,
|
||
|
i * 40 + 370
|
||
|
);
|
||
|
}
|
||
|
|
||
|
vm.imgSrc = canvas.toDataURL("image/jpeg");
|
||
|
canvas = null;
|
||
|
$h.loadClear();
|
||
|
})
|
||
|
.catch(function (error) {
|
||
|
$h.loadClear();
|
||
|
console.error(error);
|
||
|
});
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
</script>
|
||
|
<style>
|
||
|
page{
|
||
|
background: #f5f5f5;
|
||
|
|
||
|
}
|
||
|
</style>
|
||
|
<style scoped lang="scss">
|
||
|
@import "@/static/style/result.scss";
|
||
|
|
||
|
.avatar {
|
||
|
position: absolute;
|
||
|
top: -46rpx;
|
||
|
left: 50%;
|
||
|
width: 134rpx;
|
||
|
height: 134rpx;
|
||
|
border: 10rpx solid #FFFFFF;
|
||
|
border-radius: 50%;
|
||
|
background-color: #E8D8B1;
|
||
|
overflow: hidden;
|
||
|
-webkit-transform: translateX(-50%);
|
||
|
-moz-transform: translateX(-50%);
|
||
|
-ms-transform: translateX(-50%);
|
||
|
-o-transform: translateX(-50%);
|
||
|
transform: translateX(-50%);
|
||
|
}
|
||
|
|
||
|
.nickname {
|
||
|
text-align: center;
|
||
|
font-weight: 500;
|
||
|
font-size: 26rpx;
|
||
|
line-height: 37rpx;
|
||
|
color: #333333;
|
||
|
}
|
||
|
.my-canvas{
|
||
|
top:0rpx;
|
||
|
left:-40rpx;
|
||
|
}
|
||
|
.head {
|
||
|
margin-top: 80rpx;
|
||
|
|
||
|
.header {
|
||
|
position: relative;
|
||
|
width: 94%;
|
||
|
margin: auto;
|
||
|
height: 1000rpx;
|
||
|
border-radius: 12rpx;
|
||
|
background-color: #FFFFFF;
|
||
|
padding-top: 90rpx;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.result {
|
||
|
width: 94%;
|
||
|
border-radius: 12rpx;
|
||
|
margin: auto;
|
||
|
background: #ffffff;
|
||
|
}
|
||
|
.result-ft{
|
||
|
margin: 126rpx -12rpx 0 !important;
|
||
|
}
|
||
|
</style>
|