|
@@ -0,0 +1,252 @@
|
|
|
|
+<template>
|
|
|
|
+ <div class="paper-template-build">
|
|
|
|
+ <div class="paper-template-build-body">
|
|
|
|
+ <!-- <paper-template-view
|
|
|
|
+ ref="PaperTemplateView"
|
|
|
|
+ class="preview-body"
|
|
|
|
+ :pages="pages"
|
|
|
|
+ :page-config="paperTempJson.pageConfig"
|
|
|
|
+ >
|
|
|
|
+ </paper-template-view> -->
|
|
|
|
+ <!-- process dom -->
|
|
|
|
+ <!-- <div v-if="elementList.length" class="element-list">
|
|
|
|
+ <elem-rich-text
|
|
|
|
+ v-for="elem in elementList"
|
|
|
|
+ :id="elem.id"
|
|
|
|
+ :key="elem.id"
|
|
|
|
+ :data="elem"
|
|
|
|
+ ></elem-rich-text>
|
|
|
|
+ </div> -->
|
|
|
|
+ <answer-template-view
|
|
|
|
+ ref="AnswerTemplateView"
|
|
|
|
+ class="preview-body"
|
|
|
|
+ :answerData="paperJson"
|
|
|
|
+ ></answer-template-view>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script>
|
|
|
|
+// import ElemRichText from "../elements/rich-text/ElemRichText.vue";
|
|
|
|
+// import PaperTemplateView from "../components/PaperTemplateView.vue";
|
|
|
|
+import AnswerTemplateView from "../components/AnswerTemplateView.vue";
|
|
|
|
+// import { deepCopy } from "../../card/plugins/utils";
|
|
|
|
+// import previewTemp from "../previewTemp";
|
|
|
|
+import { paperDetailInfoApi } from "../../paper/api";
|
|
|
|
+// import { paperTemplateListApi, paperPdfDownloadApi } from "../api";
|
|
|
|
+import { paperPdfDownloadApi } from "../api";
|
|
|
|
+import { downloadByApi } from "@/plugins/download";
|
|
|
|
+import paperTemplateBuildMixins from "./paperTemplateBuildMixins";
|
|
|
|
+
|
|
|
|
+export default {
|
|
|
|
+ name: "AnswerTemplateBuild",
|
|
|
|
+ components: { AnswerTemplateView },
|
|
|
|
+ mixins: [paperTemplateBuildMixins],
|
|
|
|
+ data() {
|
|
|
|
+ return {
|
|
|
|
+ paperId: this.$route.params.paperId,
|
|
|
|
+ viewType: this.$route.params.viewType,
|
|
|
|
+ seqMode: "MODE3",
|
|
|
|
+ paperJson: {},
|
|
|
|
+ paperTempJson: {
|
|
|
|
+ pages: [],
|
|
|
|
+ pageConfig: {},
|
|
|
|
+ },
|
|
|
|
+ maxColumnWidth: 200,
|
|
|
|
+ maxColumnHeight: 200,
|
|
|
|
+ paperTempList: [],
|
|
|
|
+ curPaperTemp: {},
|
|
|
|
+ downloading: false,
|
|
|
|
+ fieldData: {},
|
|
|
|
+ paperStructs: [],
|
|
|
|
+ configModalForm: {
|
|
|
|
+ showDetailNo: true,
|
|
|
|
+ showDetailScoreInfo: true,
|
|
|
|
+ showDetailScoreTable: false,
|
|
|
|
+ pageCountMode: "SIMPLE",
|
|
|
|
+ },
|
|
|
|
+ configSources: [],
|
|
|
|
+ prepareDownloadPdf: false,
|
|
|
|
+ };
|
|
|
|
+ },
|
|
|
|
+ mounted() {
|
|
|
|
+ if (this.viewType === "frame") {
|
|
|
|
+ this.initFrame();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ methods: {
|
|
|
|
+ async initFrame() {
|
|
|
|
+ try {
|
|
|
|
+ const answerSet = window.parent.answerSet;
|
|
|
|
+ if (!answerSet) {
|
|
|
|
+ this.emitFrameResult(false, "数据缺失");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.seqMode = answerSet.seqMode;
|
|
|
|
+ this.curPaperTemp = answerSet.paperTemp;
|
|
|
|
+ this.configModalForm = answerSet.configModalForm;
|
|
|
|
+
|
|
|
|
+ await this.getPaperJson();
|
|
|
|
+ } catch (error) {
|
|
|
|
+ this.emitFrameResult(false, "数据错误");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
+ this.emitFrameResult(true, "", this.getPreviewTemp());
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ emitFrameResult(success = true, errorMsg = "", htmlCont = "") {
|
|
|
|
+ alert("success:" + success, errorMsg, htmlCont);
|
|
|
|
+ // window.parent &&
|
|
|
|
+ // window.parent.submitPaperTemp &&
|
|
|
|
+ // window.parent.submitPaperTemp({
|
|
|
|
+ // success,
|
|
|
|
+ // errorMsg,
|
|
|
|
+ // htmlCont,
|
|
|
|
+ // templateId: this.curPaperTemp.id,
|
|
|
|
+ // });
|
|
|
|
+ },
|
|
|
|
+ async getPaperJson() {
|
|
|
|
+ const res = await paperDetailInfoApi({
|
|
|
|
+ paperId: this.paperId,
|
|
|
|
+ seqMode: this.seqMode,
|
|
|
|
+ });
|
|
|
|
+ this.paperJson = res.data;
|
|
|
|
+ this.resetClozeSerialNo(this.paperJson);
|
|
|
|
+ this.fieldData = {
|
|
|
|
+ paperName: res.data.name,
|
|
|
|
+ courseName: res.data.course.name,
|
|
|
|
+ courseCode: res.data.course.code,
|
|
|
|
+ totalScore: res.data.totalScore,
|
|
|
|
+ rootOrgName: res.data.rootOrgName,
|
|
|
|
+ };
|
|
|
|
+ this.paperStructs = this.paperJson.paperDetails.map((detail) => {
|
|
|
|
+ return {
|
|
|
|
+ detailName: detail.name,
|
|
|
|
+ questionCount: detail.unitCount,
|
|
|
|
+ totalScore: detail.score,
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ resetClozeSerialNo(paperData) {
|
|
|
|
+ const clozeQuestionTypes = ["CLOZE", "BANKED_CLOZE"];
|
|
|
|
+ paperData.paperDetails.forEach((detail) => {
|
|
|
|
+ detail.paperDetailUnits.forEach((question) => {
|
|
|
|
+ if (!clozeQuestionTypes.includes(question.questionType)) return;
|
|
|
|
+ question.question.quesBody.sections.forEach((section) => {
|
|
|
|
+ section.blocks.forEach((block) => {
|
|
|
|
+ if (block.type !== "cloze") return;
|
|
|
|
+ block.value =
|
|
|
|
+ question.question.subQuestions[block.value - 1].questionSeq;
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ // img ------ start >
|
|
|
|
+ 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" && elem.value.startsWith("http")) {
|
|
|
|
+ urls.push(elem.value);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ return urls;
|
|
|
|
+ },
|
|
|
|
+ async waitAllImgLoaded() {
|
|
|
|
+ let imgUrls = [];
|
|
|
|
+ this.elementList.forEach((item) => {
|
|
|
|
+ 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();
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ // img ------ end >
|
|
|
|
+ // download ------ start >
|
|
|
|
+ getPreviewTemp() {
|
|
|
|
+ // return previewTemp(this.$refs.PaperTemplateView.$el.outerHTML);
|
|
|
|
+ },
|
|
|
|
+ async downloadPaperPdf() {
|
|
|
|
+ const htmlCont = this.getPreviewTemp();
|
|
|
|
+
|
|
|
|
+ if (this.downloading) return;
|
|
|
|
+ this.downloading = true;
|
|
|
|
+
|
|
|
|
+ const res = await downloadByApi(() => {
|
|
|
|
+ return paperPdfDownloadApi({
|
|
|
|
+ content: htmlCont,
|
|
|
|
+ templateId: this.curPaperTemp.id,
|
|
|
|
+ paperId: this.paperId,
|
|
|
|
+ });
|
|
|
|
+ }).catch((e) => {
|
|
|
|
+ this.$message.error(e || "下载失败,请重新尝试!");
|
|
|
|
+ });
|
|
|
|
+ this.downloading = false;
|
|
|
|
+
|
|
|
|
+ if (!res) return;
|
|
|
|
+ this.$message.success("下载成功!");
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+};
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<style>
|
|
|
|
+.paper-template-build {
|
|
|
|
+ text-align: center;
|
|
|
|
+}
|
|
|
|
+.paper-template-build-body {
|
|
|
|
+ display: inline-block;
|
|
|
|
+ text-align: initial;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.paper-template-build .page-box {
|
|
|
|
+ margin-top: 10px;
|
|
|
|
+ margin-bottom: 10px;
|
|
|
|
+}
|
|
|
|
+.paper-template-build .paper-build-config {
|
|
|
|
+ padding: 10px 15px 2px;
|
|
|
|
+ margin-top: 5px;
|
|
|
|
+ background: #fff;
|
|
|
|
+ border-radius: 10px;
|
|
|
|
+}
|
|
|
|
+.paper-build-config .el-form-item {
|
|
|
|
+ margin-bottom: 16px;
|
|
|
|
+ margin-right: 30px;
|
|
|
|
+}
|
|
|
|
+.paper-template-build .element-list {
|
|
|
|
+ visibility: hidden;
|
|
|
|
+ position: absolute;
|
|
|
|
+ width: 1200px;
|
|
|
|
+ height: 600px;
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ left: -9999px;
|
|
|
|
+ top: 0;
|
|
|
|
+ z-index: 1;
|
|
|
|
+}
|
|
|
|
+</style>
|