|
@@ -3,22 +3,53 @@
|
|
|
class="preview-paper-dialog"
|
|
|
:visible.sync="visible"
|
|
|
title="查看原卷"
|
|
|
- width="1200px"
|
|
|
top="0"
|
|
|
:close-on-click-modal="false"
|
|
|
:close-on-press-escape="false"
|
|
|
append-to-body
|
|
|
+ fullscreen
|
|
|
+ destroy-on-close
|
|
|
@open="visibleChange"
|
|
|
>
|
|
|
+ <div ref="PaperBody" class="paper-body">
|
|
|
+ <div
|
|
|
+ v-if="renderStructList.length"
|
|
|
+ class="paper-content paper-content-long"
|
|
|
+ >
|
|
|
+ <cont-item
|
|
|
+ v-for="(item, index) in renderStructList"
|
|
|
+ :key="index"
|
|
|
+ :data="item"
|
|
|
+ ></cont-item>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ v-for="(group, gindex) in renderGroupStructList"
|
|
|
+ :key="gindex"
|
|
|
+ class="paper-content"
|
|
|
+ >
|
|
|
+ <cont-item
|
|
|
+ v-for="(item, index) in group"
|
|
|
+ :key="index"
|
|
|
+ :data="item"
|
|
|
+ ></cont-item>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
<div slot="footer"></div>
|
|
|
</el-dialog>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import { studentExamDetailInfo } from "@/api/examwork-student";
|
|
|
+import { numberToChinese, numberToUpperCase } from "./spins/renderJSON";
|
|
|
+import ContItem from "./spins/ContItem.vue";
|
|
|
+import previewTem from "./spins/previewTem";
|
|
|
+import { randomCode } from "@/utils/utils";
|
|
|
|
|
|
export default {
|
|
|
name: "preview-paper-dialog",
|
|
|
+ components: { ContItem },
|
|
|
props: {
|
|
|
examRecordId: {
|
|
|
type: String,
|
|
@@ -27,10 +58,16 @@ export default {
|
|
|
data() {
|
|
|
return {
|
|
|
visible: false,
|
|
|
+ paperStruct: {},
|
|
|
+ renderStructList: [],
|
|
|
+ renderGroupStructList: [],
|
|
|
};
|
|
|
},
|
|
|
methods: {
|
|
|
visibleChange() {
|
|
|
+ this.paperStruct = {};
|
|
|
+ this.renderStructList = [];
|
|
|
+ this.renderGroupStructList = [];
|
|
|
this.getRecordDetail();
|
|
|
},
|
|
|
openDialog() {
|
|
@@ -41,13 +78,245 @@ export default {
|
|
|
},
|
|
|
async getRecordDetail() {
|
|
|
const res = await studentExamDetailInfo(this.examRecordId);
|
|
|
- const paperStructJson = JSON.parse(res.data.data.paperStructJson);
|
|
|
- const answerJson = JSON.parse(res.data.data.answerJson);
|
|
|
- const examStudentAnswerJson = JSON.parse(
|
|
|
- res.data.data.examStudentAnswerJson
|
|
|
- );
|
|
|
- console.log(paperStructJson, answerJson, examStudentAnswerJson);
|
|
|
+ this.parsePaperStruct(res.data.data);
|
|
|
+ this.parseRenderStructList();
|
|
|
+
|
|
|
+ const loadres = await this.waitAllImgLoaded().catch(() => {});
|
|
|
+ if (!loadres) {
|
|
|
+ this.$message.error("图片加载有误!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.buildRenderGroupStructList();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ parsePaperStruct(data) {
|
|
|
+ const paperStructJson = JSON.parse(data.paperStructJson);
|
|
|
+ const answerJson = JSON.parse(data.answerJson);
|
|
|
+ const examStudentAnswerJson = data.examStudentAnswerJson
|
|
|
+ ? JSON.parse(data.examStudentAnswerJson)
|
|
|
+ : [];
|
|
|
+ console.log(paperStructJson);
|
|
|
+ console.log(answerJson);
|
|
|
+ console.log(examStudentAnswerJson);
|
|
|
+
|
|
|
+ const answerMap = {};
|
|
|
+ answerJson.details.forEach((detail) => {
|
|
|
+ detail.questions.forEach((question) => {
|
|
|
+ const k = `${detail.number}-${question.number}`;
|
|
|
+ if (question.subQuestions) {
|
|
|
+ question.subQuestions.forEach((sq) => {
|
|
|
+ answerMap[`${k}-${sq.number}`] = sq.answer;
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ answerMap[k] = question.answer;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ const studentAnsMap = {};
|
|
|
+ examStudentAnswerJson.forEach((question) => {
|
|
|
+ const k = `${question.mainNumber}-${question.subNumber}`;
|
|
|
+ if (question.subQuestions) {
|
|
|
+ question.subQuestions.forEach((sq) => {
|
|
|
+ studentAnsMap[`${k}-${sq.number}`] = JSON.parse(sq.answer);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ studentAnsMap[k] = JSON.parse(question.answer);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // detail
|
|
|
+ paperStructJson.details.forEach((detail) => {
|
|
|
+ detail.questions.forEach((question) => {
|
|
|
+ let k = `${detail.number}-${question.number}`;
|
|
|
+ if (question.subQuestions) {
|
|
|
+ question.subQuestions.forEach((sq) => {
|
|
|
+ k += `-${sq.number}`;
|
|
|
+ sq.answer = answerMap[k];
|
|
|
+ sq.studentAnswer = studentAnsMap[k];
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ question.answer = answerMap[k];
|
|
|
+ question.studentAnswer = studentAnsMap[k];
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ console.log(JSON.stringify(paperStructJson));
|
|
|
+ this.paperStruct = paperStructJson;
|
|
|
+ },
|
|
|
+ parseRenderStructList() {
|
|
|
+ let renderStructList = [];
|
|
|
+ renderStructList.push({
|
|
|
+ cls: "paper-name",
|
|
|
+ type: "text",
|
|
|
+ content: this.paperStruct.name,
|
|
|
+ });
|
|
|
+ this.paperStruct.details.forEach((detail) => {
|
|
|
+ renderStructList.push({
|
|
|
+ cls: "detail-name",
|
|
|
+ type: "text",
|
|
|
+ content: `${numberToChinese(detail.number)}、${detail.name}`,
|
|
|
+ });
|
|
|
+
|
|
|
+ detail.questions.forEach((question) => {
|
|
|
+ if (question.subQuestions) {
|
|
|
+ if (question.body) {
|
|
|
+ renderStructList.push({
|
|
|
+ cls: "topic-title",
|
|
|
+ type: "json",
|
|
|
+ content: {
|
|
|
+ isCommon: true,
|
|
|
+ number: question.number,
|
|
|
+ body: question.body,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }
|
|
|
+ question.subQuestions.forEach((sq) => {
|
|
|
+ const contents = this.parseSimpleQuestion(sq, false);
|
|
|
+ renderStructList.push(...contents);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ const contents = this.parseSimpleQuestion(question, true);
|
|
|
+ renderStructList.push(...contents);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ this.renderStructList = renderStructList.map((item) => {
|
|
|
+ item.id = randomCode();
|
|
|
+ return item;
|
|
|
+ });
|
|
|
+ console.log(renderStructList);
|
|
|
+ },
|
|
|
+ parseSimpleQuestion(question, isCommon) {
|
|
|
+ let contents = [];
|
|
|
+ contents.push({
|
|
|
+ cls: "topic-title",
|
|
|
+ type: "json",
|
|
|
+ content: {
|
|
|
+ isSub: !isCommon,
|
|
|
+ number: question.number,
|
|
|
+ body: question.body,
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ if (question.options && question.options.length) {
|
|
|
+ question.options.forEach((op) => {
|
|
|
+ contents.push({
|
|
|
+ cls: "topic-option",
|
|
|
+ type: "json",
|
|
|
+ content: {
|
|
|
+ isSub: false,
|
|
|
+ number: numberToUpperCase(op.number),
|
|
|
+ body: op.body,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ if (question.answer) {
|
|
|
+ contents.push({
|
|
|
+ cls: "topic-answer",
|
|
|
+ type: "json",
|
|
|
+ content: {
|
|
|
+ answerType: "standard",
|
|
|
+ structType: question.structType,
|
|
|
+ body: question.answer,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (question.studentAnswer) {
|
|
|
+ contents.push({
|
|
|
+ cls: "topic-answer std-answer",
|
|
|
+ type: "json",
|
|
|
+ content: {
|
|
|
+ answerType: "student",
|
|
|
+ structType: question.structType,
|
|
|
+ body: question.studentAnswer,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ return contents;
|
|
|
+ },
|
|
|
+ loadImg(url) {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ const img = new Image();
|
|
|
+ img.onload = function () {
|
|
|
+ resolve(true);
|
|
|
+ };
|
|
|
+ img.onerror = function () {
|
|
|
+ reject();
|
|
|
+ };
|
|
|
+ img.src = url;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ getRichJsonImgUrls(richJson) {
|
|
|
+ let urls = [];
|
|
|
+ richJson.sections.forEach((section) => {
|
|
|
+ section.blocks.forEach((elem) => {
|
|
|
+ if (elem.type === "image") {
|
|
|
+ urls.push(elem.value);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ return urls;
|
|
|
+ },
|
|
|
+ async waitAllImgLoaded() {
|
|
|
+ let imgUrls = [];
|
|
|
+ this.renderStructList.forEach((item) => {
|
|
|
+ if (item.type === "text") return;
|
|
|
+ if (item.cls === "topic-title" || item.cls === "topic-option") {
|
|
|
+ imgUrls.push(...this.getRichJsonImgUrls(item.content.body));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 简答题才可能会有图片
|
|
|
+ if (item.cls.indexOf("answer") && item.content.structType === 5) {
|
|
|
+ item.content.body.forEach((body) => {
|
|
|
+ imgUrls.push(...this.getRichJsonImgUrls(body));
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ console.log(imgUrls);
|
|
|
+
|
|
|
+ if (!imgUrls.length) return Promise.resolve(true);
|
|
|
+ const imgLoads = imgUrls.map((item) => this.loadImg(item));
|
|
|
+ const imgLoadResult = await Promise.all(imgLoads).catch(() => {});
|
|
|
+ if (imgLoadResult && imgLoadResult.length) {
|
|
|
+ return Promise.resolve(true);
|
|
|
+ } else {
|
|
|
+ return Promise.reject();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ buildRenderGroupStructList() {
|
|
|
+ const pageMaxHeight = 1042;
|
|
|
+ let curGroup = [],
|
|
|
+ curGroupHeight = 0;
|
|
|
+ let renderGroupStructList = [];
|
|
|
+ this.renderStructList.forEach((item) => {
|
|
|
+ const itemHeight = document.getElementById(item.id).clientHeight;
|
|
|
+ if (curGroupHeight + itemHeight > pageMaxHeight) {
|
|
|
+ if (curGroup.length) renderGroupStructList.push(curGroup);
|
|
|
+ curGroup = [];
|
|
|
+ curGroupHeight = 0;
|
|
|
+ }
|
|
|
+ curGroup.push(item);
|
|
|
+ curGroupHeight += itemHeight;
|
|
|
+ });
|
|
|
+
|
|
|
+ if (curGroup.length) renderGroupStructList.push(curGroup);
|
|
|
+
|
|
|
+ this.renderGroupStructList = renderGroupStructList;
|
|
|
+ this.renderStructList = [];
|
|
|
+ },
|
|
|
+ getPreviewHtml() {
|
|
|
+ const html = previewTem(this.$refs.PaperBody.innerHTML);
|
|
|
+ console.log(html);
|
|
|
},
|
|
|
},
|
|
|
};
|
|
|
</script>
|
|
|
+
|
|
|
+<style src="@/styles/paper-preview.css"></style>
|