123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367 |
- <template>
- <el-dialog
- class="preview-paper-dialog"
- :visible.sync="visible"
- title="查看原卷"
- 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";
- import { STRUCT_TYPES } from "./spins/paperSetting";
- export default {
- name: "preview-paper-dialog",
- components: { ContItem },
- props: {
- examRecordId: {
- type: String,
- },
- },
- data() {
- return {
- visible: false,
- paperStruct: {},
- renderStructList: [],
- renderGroupStructList: [],
- };
- },
- methods: {
- visibleChange() {
- this.paperStruct = {};
- this.renderStructList = [];
- this.renderGroupStructList = [];
- this.getRecordDetail();
- },
- openDialog() {
- this.visible = true;
- },
- closeDialog() {
- this.visible = false;
- },
- async getRecordDetail() {
- const res = await studentExamDetailInfo(this.examRecordId);
- 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.subIndex !== null) {
- studentAnsMap[`${k}-${question.subIndex}`] = {
- answer: JSON.parse(question.answer),
- score: question.score,
- };
- } else {
- studentAnsMap[k] = {
- answer: JSON.parse(question.answer),
- score: question.score,
- };
- }
- });
- // detail
- paperStructJson.details.forEach((detail) => {
- detail.questions.forEach((question) => {
- let k = `${detail.number}-${question.number}`;
- if (question.subQuestions) {
- question.subQuestions.forEach((sq) => {
- const sqk = `${k}-${sq.number}`;
- sq.answer = answerMap[sqk];
- const stdAns = studentAnsMap[sqk] || {
- answer: null,
- score: null,
- };
- sq.studentAnswer = stdAns.answer;
- sq.studentScore = stdAns.score;
- });
- } else {
- question.answer = answerMap[k];
- const stdAns = studentAnsMap[k] || { answer: null, score: null };
- question.studentAnswer = stdAns.answer;
- question.studentScore = stdAns.score;
- }
- });
- });
- // 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) {
- // 简答题的特殊处理,解决上传的大图无法分页问题。文字内容不受影响。
- if (question.structType === STRUCT_TYPES.TEXT) {
- // console.log(question.studentAnswer);
- let aindex = 0;
- question.studentAnswer.forEach((answer) => {
- answer.sections.forEach((section) => {
- contents.push({
- cls: "topic-answer std-answer",
- type: "json",
- content: {
- answerType: "student",
- structType: question.structType,
- hideTitle: aindex !== 0,
- body: [
- {
- sections: [section],
- },
- ],
- },
- });
- aindex++;
- });
- });
- } else {
- // console.log(question.studentAnswer);
- contents.push({
- cls: "topic-answer std-answer",
- type: "json",
- content: {
- answerType: "student",
- structType: question.structType,
- body: question.studentAnswer,
- },
- });
- }
- }
- contents.push({
- cls: "topic-score",
- type: "text",
- content: "得分:" + (question.studentScore || 0),
- });
- 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>
|