import { CARD_VERSION } from "../enumerate"; import { deepCopy } from "../plugins/utils"; const initIndex = { question: 1, absent: 1, breach: 1, paperType: 1, examNumber: 1, selective: 1, pageNumber: 1, }; /** * 格式文档:https://doc.qmth.com.cn/pages/viewpage.action?pageId=19661052 */ export default { data() { return { fillAreaIndex: { ...initIndex, }, VALID_ELEMENTS_FOR_EXTERNAL: [ "LOCATOR", "BARCODE", "CARD_HEAD", "FILL_QUESTION", "FILL_LINE", "EXPLAIN", "COMPOSITION", ], curPageOffsetInfo: {}, curPageDom: null, }; }, methods: { getFillAreaIndex(type) { return this.fillAreaIndex[type]++; }, getElementHumpName(cont) { return cont .split("_") .map((item) => item[0] + item.substr(1).toLowerCase()) .join(""); }, getPreviewElementById(id) { return document.getElementById(`preview-${id}`); }, parsePageExchange(pages) { const npages = deepCopy(pages); // 单页题卡不显示页码涂块 this.curPageOffsetInfo = document .getElementById(`preview-page-box-0`) .getBoundingClientRect(); const pageNumberInfo = pages.length <= 2 ? null : this.getPageNumberInfo(); npages.forEach((page, pindex) => { this.curPageDom = document.getElementById(`preview-page-box-${pindex}`); this.curPageOffsetInfo = this.curPageDom.getBoundingClientRect(); let exchange = { card_type: 2, page_size: page.pageSize, page_image: "", locator: this.getLocatorInfo(this.curPageDom), fill_locator: [], check_area: { black_line: [], white_line: [], }, barcode: [], qrcode: [], ocr_area: [], info_area: [], fill_area: [], answer_area: [], extension: { barcode: [], fill_area: [], ocr_area: [], qrcode: [], }, }; const elements = [ page.globals, ...page.columns.map((column) => column.elements), ]; elements.forEach((elemGroup) => { elemGroup.forEach((element) => { if (this.VALID_ELEMENTS_FOR_EXTERNAL.includes(element.type)) { const funcName = this.getElementHumpName(element.type); // console.log(funcName); const info = this[`get${funcName}Info`](element); Object.entries(info).forEach(([key, vals]) => { exchange[key] = exchange[key].concat(vals); }); } }); }); if (!(pindex % 2) && pageNumberInfo) { let pnoInfo = deepCopy(pageNumberInfo); pnoInfo[0].index = this.getFillAreaIndex("pageNumber"); exchange.fill_area = exchange.fill_area.concat(pnoInfo); } // 课程代码条码 const extraInfo = this.getExtraInfo(this.curPageDom); Object.entries(extraInfo).forEach(([key, vals]) => { exchange.extension[key] = exchange.extension[key].concat(vals); }); // 考生承诺书 const uAreas = this.getUndertakingInfo(this.curPageDom); exchange.info_area.push(...uAreas); page.exchange = exchange; }); this.fillAreaIndex = { ...initIndex }; return npages; }, getUndertakingInfo(pageDom) { const areas = []; const undertakingDom = pageDom.querySelector(".elem-undertaking"); if (undertakingDom) { areas.push(this.getOffsetInfo(undertakingDom)); } return areas; }, getExtraInfo(pageDom) { const info = { barcode: [], }; const courseBarDom = pageDom.querySelector(".course-barcode"); if (courseBarDom) { info.barcode.push({ field: "courseCode", area: this.getOffsetInfo(courseBarDom), }); } return info; }, getPageNumberInfo() { const dom = document.getElementById(`preview-page-box-0`); let options = []; dom .querySelector(".page-number-rect-list") .childNodes.forEach((item, index) => { options[index] = this.getOffsetInfo(item); }); // console.log(options); return [ { field: "pageNumber", index: 1, single: true, horizontal: true, items: [ { main_number: null, sub_number: null, options, recog_info: [], }, ], }, ]; }, getLocatorInfo(curPageDom) { let tops = []; curPageDom .querySelector(".page-locator-top") .childNodes.forEach((item) => { tops.push(this.getOffsetInfo(item)); }); let bottoms = []; curPageDom .querySelector(".page-locator-bottom") .childNodes.forEach((item) => { bottoms.push(this.getOffsetInfo(item)); }); return { top: tops, bottom: bottoms, }; }, getCardHeadInfo(element) { const dom = this.getPreviewElementById(element.id); const headArea = this.getOffsetInfo(dom); let fill_area = []; let barcode = []; // 学生学号 if (element.examNumberStyle === "FILL") { // fill_area let listInfos = []; dom .querySelectorAll(".stdno-fill-list") .forEach((questionItem, questionIndex) => { let options = []; questionItem.childNodes.forEach((optionItem, optionIndex) => { options[optionIndex] = this.getOffsetInfo(optionItem); }); listInfos[questionIndex] = { main_number: null, sub_number: null, options, recog_info: [], }; }); fill_area.push({ field: "examNumber", index: this.getFillAreaIndex("examNumber"), single: true, horizontal: false, items: listInfos, }); } else { // barcode const stdnoDom = element.columnNumber <= 2 ? dom.querySelector(".head-stdno").parentNode : dom.querySelector(".head-stdno"); barcode.push({ field: "examNumber", area: this.getOffsetInfo(stdnoDom), }); } // 缺考涂填 if (element.examAbsent && !element.isSimple) { fill_area.push({ field: "absent", index: this.getFillAreaIndex("absent"), single: true, horizontal: true, items: [ { main_number: null, sub_number: null, options: [ this.getOffsetInfo(dom.querySelector(".dynamic-miss-area")), ], recog_info: [], }, ], }); } // 违纪标记 if (element.discipline && !element.isSimple) { fill_area.push({ field: "breach", index: this.getFillAreaIndex("breach"), single: true, horizontal: true, items: [ { main_number: null, sub_number: null, options: [ this.getOffsetInfo(dom.querySelector(".dynamic-breach-area")), ], recog_info: [], }, ], }); } // A/B卷类型 if (element.aOrB && !element.isSimple) { if (element.paperType === "PRINT") { // barcode barcode.push({ field: "paperType", area: this.getOffsetInfo( dom.querySelector(".dynamic-aorb-barcode") ), }); } else { // fill_area let options = []; dom .querySelector(".head-dynamic-aorb") .querySelectorAll(".head-dynamic-rect") .forEach((optionItem, optionIndex) => { options[optionIndex] = this.getOffsetInfo(optionItem); }); fill_area.push({ field: "paperType", index: this.getFillAreaIndex("paperType"), single: true, horizontal: true, items: [ { main_number: null, sub_number: null, options, recog_info: [], }, ], }); } } return { info_area: [headArea], fill_area, barcode, }; }, getFillQuestionInfo(element) { const dom = this.getPreviewElementById(element.id); const single = !element.isMultiply; const horizontal = element.optionDirection === "horizontal"; let fillAreas = []; dom.querySelectorAll(".group-item").forEach((groupItem) => { let listInfos = []; groupItem .querySelectorAll(".question-item") .forEach((questionItem, questionIndex) => { let options = []; questionItem.childNodes.forEach((optionItem, optionIndex) => { if (optionIndex) options[optionIndex - 1] = this.getOffsetInfo(optionItem); }); listInfos[questionIndex] = { main_number: element.topicNo, sub_number: questionItem.firstChild.textContent * 1, options, recog_info: [], }; }); fillAreas.push({ field: "question", index: this.getFillAreaIndex("question"), single, horizontal, items: listInfos, }); }); return { fill_area: fillAreas, }; }, getFillLineInfo(element) { const dom = this.getPreviewElementById(element.id); let sub_numbers = []; for ( let i = element.startNumber, len = element.startNumber + element.questionsCount; i < len; i++ ) { sub_numbers.push(i); } return { answer_area: [ { main_number: element.topicNo, sub_number: sub_numbers.join(), area: this.getOffsetInfo(dom), }, ], }; }, getExplainInfo(element) { const dom = this.getPreviewElementById(element.id); return { answer_area: [ { main_number: element.topicNo, sub_number: element.serialNumber, area: this.getOffsetInfo(dom), }, ], }; }, getCompositionInfo(element) { const dom = this.getPreviewElementById(element.id); return { answer_area: [ { main_number: element.topicNo, sub_number: 1, area: this.getOffsetInfo(dom), }, ], }; }, getOffsetInfo(dom) { const { width: domW, height: domH, left: domL, top: domT, } = dom.getBoundingClientRect(); const { width: pageW, height: pageH, left: pageL, top: pageT, } = this.curPageOffsetInfo; // [x,y,w,h] const infos = [ (domL - pageL) / pageW, (domT - pageT) / pageH, domW / pageW, domH / pageH, ]; return infos.map((num) => num.toFixed(10) * 1); }, getPageModel({ cardConfig, pages, answers = {} }) { let npages = this.parsePageExchange(pages); return JSON.stringify( { version: CARD_VERSION, cardType: "STANDARD", cardConfig, pages: npages, answers, }, (k, v) => (k.startsWith("_") ? undefined : v) ); }, }, };