123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554 |
- <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, MAX_WIDTH, MAX_HEIGHT } from "./spins/paperSetting";
- const OPTION_NAME = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- 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();
- });
- },
- checkIsMatches(structType) {
- const matchesTypes = [8, 9, 10];
- return matchesTypes.includes(structType);
- },
- parsePaperStruct(data) {
- const paperStructJson = data.paperStructJson
- ? JSON.parse(data.paperStructJson)
- : { details: [] };
- const answerJson = data.answerJson
- ? JSON.parse(data.answerJson)
- : { details: [] };
- const examStudentAnswerJson = data.examStudentAnswerJson
- ? JSON.parse(data.examStudentAnswerJson)
- : [];
- const subjectiveScoreDetailJson = data.subjectiveScoreDetailJson
- ? JSON.parse(data.subjectiveScoreDetailJson)
- : [];
- const randomPaperStructPath = data.randomPaperStructPath
- ? JSON.parse(data.randomPaperStructPath)
- : { details: [] };
- // console.log(JSON.stringify(randomPaperStructPath));
- // console.log(paperStructJson);
- // console.log(answerJson);
- // console.log(examStudentAnswerJson);
- const isEmpty = (cont) =>
- cont === undefined || cont === null || cont === "";
- 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,
- };
- }
- });
- subjectiveScoreDetailJson.forEach((question) => {
- let k = `${question.mainNumber}-${question.subNumber}`;
- if (question.subIndex) {
- k = `${k}-${question.subIndex}`;
- }
- if (studentAnsMap[k]) {
- studentAnsMap[k].score = question.score;
- } else {
- studentAnsMap[k] = {
- score: question.score,
- answer: null,
- };
- }
- });
- // detail
- paperStructJson.details.forEach((detail) => {
- detail.questions.forEach((question) => {
- let k = `${detail.number}-${question.number}`;
- if (question.subQuestions) {
- const isMatches = this.checkIsMatches(question.structType);
- question.subQuestions.forEach((sq) => {
- if (isMatches) sq.options = [];
- const sqk = `${k}-${sq.number}`;
- sq.answer = isEmpty(answerMap[sqk]) ? null : answerMap[sqk];
- const stdAns = studentAnsMap[sqk] || {
- answer: null,
- score: null,
- };
- sq.studentAnswer = stdAns.answer;
- sq.studentScore = stdAns.score;
- });
- } else {
- question.answer = isEmpty(answerMap[k]) ? null : answerMap[k];
- const stdAns = studentAnsMap[k] || { answer: null, score: null };
- question.studentAnswer = stdAns.answer;
- question.studentScore = stdAns.score;
- }
- });
- });
- let studentPaperStructJson = { ...paperStructJson };
- if (randomPaperStructPath.details.length) {
- studentPaperStructJson.details = randomPaperStructPath.details.map(
- (detail, dindex) => {
- const rDetail = { ...paperStructJson.details[detail.number - 1] };
- rDetail.number = dindex + 1;
- rDetail.questions = detail.questions.map((question, qindex) => {
- // 试题乱序
- const rQuestion = { ...rDetail.questions[question.number - 1] };
- rQuestion.number = qindex + 1;
- if (question.options) {
- // 选项乱序
- let optionMap = {};
- rQuestion.options = question.options.map((opNo, oindex) => {
- const rOption = { ...rQuestion.options[opNo - 1] };
- rOption.number = oindex + 1;
- optionMap[opNo] = oindex + 1;
- return rOption;
- });
- if (rQuestion.answer) {
- rQuestion.answer = rQuestion.answer.map(
- (ans) => optionMap[ans]
- );
- }
- if (rQuestion.studentAnswer) {
- rQuestion.studentAnswer = rQuestion.studentAnswer.map(
- (ans) => optionMap[ans]
- );
- }
- }
- return rQuestion;
- });
- return rDetail;
- }
- );
- }
- this.paperStruct = studentPaperStructJson;
- },
- transformRichJson(richJson) {
- let contents = [];
- let curBlock = [];
- const checkNeedSplitSection = (block) => {
- if (block.type !== "image") return false;
- if (block.param) {
- if (block.param.width) return block.param.width > MAX_WIDTH / 2;
- if (block.param.height) return block.param.height > 150;
- }
- return true;
- };
- richJson.sections.forEach((section) => {
- section.blocks.forEach((block) => {
- if (checkNeedSplitSection(block) && curBlock.length) {
- contents.push({ sections: [{ blocks: [...curBlock] }] });
- curBlock = [];
- }
- curBlock.push(block);
- });
- if (curBlock.length) {
- contents.push({ sections: [{ blocks: [...curBlock] }] });
- curBlock = [];
- }
- });
- return contents;
- },
- 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}`,
- });
- const dbodys = this.parseTopicDesc(detail.description);
- renderStructList.push(...dbodys);
- detail.questions.forEach((question) => {
- if (question.subQuestions) {
- const bodys = this.parseTopicTitle(
- question.body,
- `${question.number}、`
- );
- renderStructList.push(...bodys);
- const isMatches = this.checkIsMatches(question.structType);
- if (isMatches && question.options && question.options.length) {
- question.options.forEach((op) => {
- const obodys = this.parseTopicOption(op.body, op.number);
- renderStructList.push(...obodys);
- });
- }
- 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 = [];
- const tbodys = this.parseTopicTitle(
- question.body,
- isCommon ? `${question.number}、` : `${question.number})`
- );
- contents.push(...tbodys);
- if (question.options && question.options.length) {
- question.options.forEach((op) => {
- const obodys = this.parseTopicOption(op.body, op.number);
- contents.push(...obodys);
- });
- }
- if (question.answer !== null) {
- // console.log(question.answer);
- const conts = this.parseTopicAnswer(
- question.answer,
- question.structType,
- false
- );
- contents.push(...conts);
- }
- if (question.studentAnswer !== null) {
- const conts = this.parseTopicAnswer(
- question.studentAnswer,
- question.structType,
- true
- );
- contents.push(...conts);
- }
- contents.push({
- cls: "topic-score",
- type: "text",
- content: "得分:" + (question.studentScore || 0),
- });
- return contents;
- },
- parseTopicDesc(richJson) {
- const bodys = this.transformRichJson(richJson);
- return bodys.map((body) => {
- return {
- cls: "detail-desc",
- type: "json",
- content: body,
- };
- });
- },
- parseTopicTitle(richJson, numberVal) {
- if (!richJson) {
- return {
- cls: "topic-title",
- type: "json",
- content: {
- sections: [
- {
- blocks: [
- {
- type: "text",
- value: numberVal,
- param: { bold: true },
- },
- ],
- },
- ],
- },
- };
- }
- const bodys = this.transformRichJson(richJson);
- return bodys.map((body, index) => {
- if (index === 0) {
- body.sections[0].blocks.unshift({
- type: "text",
- value: numberVal,
- param: { bold: true },
- });
- }
- return {
- cls: "topic-title",
- type: "json",
- content: body,
- };
- });
- },
- parseTopicOption(richJson, number) {
- const bodys = this.transformRichJson(richJson);
- return bodys.map((body, index) => {
- if (index === 0) {
- body.sections[0].blocks.unshift({
- type: "text",
- value: `${numberToUpperCase(number)}、`,
- });
- }
- return {
- cls: "topic-option",
- type: "json",
- content: body,
- };
- });
- },
- parseTopicAnswer(answer, structType, isStdAns) {
- // console.log(answer, structType, isStdAns);
- const answerTitleBlock = {
- type: "text",
- value: isStdAns ? "学生答案:" : "标准答案:",
- param: {
- bold: true,
- },
- };
- let contents = [];
- if (
- structType === STRUCT_TYPES.FILL_BLANK ||
- structType === STRUCT_TYPES.TEXT
- ) {
- contents.push({
- cls: "topic-answer",
- type: "json",
- content: {
- sections: [
- {
- blocks: [{ ...answerTitleBlock }],
- },
- ],
- },
- });
- answer.forEach((item) => {
- const bodys = this.transformRichJson(item);
- const conts = bodys.map((body, index) => {
- if (index === 0) {
- // body.sections[0].blocks.unshift({
- // type: "text",
- // value: "",
- // });
- }
- return {
- cls: "topic-answer",
- type: "json",
- content: body,
- };
- });
- contents.push(...conts);
- });
- } else {
- let ansCont = "";
- if (structType === STRUCT_TYPES.BOOLEAN_CHOICE) {
- ansCont = answer ? "对" : "错";
- } else {
- ansCont = answer.map((item) => OPTION_NAME[item - 1]).join("");
- }
- contents.push({
- cls: "topic-answer",
- type: "json",
- content: {
- sections: [
- {
- blocks: [
- { ...answerTitleBlock },
- { type: "text", value: ansCont },
- ],
- },
- ],
- },
- });
- }
- 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 = [];
- if (!richJson) return 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;
- imgUrls.push(...this.getRichJsonImgUrls(item.content));
- });
- // 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() {
- let curGroup = [],
- curGroupHeight = 0;
- let renderGroupStructList = [];
- this.renderStructList.forEach((item) => {
- const itemHeight = document.getElementById(item.id).clientHeight;
- if (curGroupHeight + itemHeight > MAX_HEIGHT) {
- 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>
|