import { CARD_VERSION } from "../../enumerate"; import { deepCopy } from "../../plugins/utils"; const initIndex = { question: 1, absent: 1, paperType: 1, examNumber: 1, selective: 1, pageNumber: 1, }; let fillAreaIndex = { ...initIndex }; let curPageOffsetInfo = {}; const VALID_ELEMENTS_FOR_EXTERNAL = [ "LOCATOR", "BARCODE", "FILL_QUESTION", "FILL_LINE", "FILL_NUMBER", "FILL_FIELD", "FILL_TABLE", "LINES", "GRIDS", ]; function initFillAreaIndex() { fillAreaIndex = { ...initIndex }; } function getFillAreaIndex(type) { return fillAreaIndex[type]++; } function getPreviewElementById(id) { return document.getElementById(`preview-${id}`); } function getOffsetInfo(dom) { const { width: domW, height: domH, left: domL, top: domT, } = dom.getBoundingClientRect(); const { width: pageW, height: pageH, left: pageL, top: pageT, } = curPageOffsetInfo; const infos = [ (domL - pageL) / pageW, (domT - pageT) / pageH, domW / pageW, domH / pageH, ]; return infos.map((num) => num.toFixed(10) * 1); } // locator: [], // barcode: [], // info_area: [], // fill_area: [], // answer_area: [] const elementInfoFunc = { LOCATOR: (curPageDom) => { let tops = []; curPageDom.querySelector(".page-locator-top").childNodes.forEach((item) => { tops.push(getOffsetInfo(item)); }); let bottoms = []; curPageDom .querySelector(".page-locator-bottom") .childNodes.forEach((item) => { bottoms.push(getOffsetInfo(item)); }); return { top: tops, bottom: bottoms, }; }, BARCODE: (element) => { return { barcode: [ { field: element.fields[0] && element.fields[0].code, area: getOffsetInfo(getPreviewElementById(element.id)), }, ], }; }, FILL_QUESTION: (element) => { const dom = 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] = getOffsetInfo(optionItem); }); listInfos[questionIndex] = { main_number: element.topicNo, sub_number: questionItem.firstChild.textContent * 1, options, recog_info: [], }; }); fillAreas.push({ field: "question", index: getFillAreaIndex("question"), single, horizontal, items: listInfos, }); }); return { fill_area: fillAreas, }; }, FILL_LINE: (element) => { const dom = 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: getOffsetInfo(dom), }, ], }; }, FILL_NUMBER: (element) => { let listInfos = []; const dom = getPreviewElementById(element.id); dom .querySelectorAll(".fill-number-list") .forEach((questionItem, questionIndex) => { let options = []; questionItem.childNodes.forEach((optionItem, optionIndex) => { options[optionIndex] = getOffsetInfo(optionItem); }); listInfos[questionIndex] = { main_number: null, sub_number: null, options, recog_info: [], }; }); return { fill_area: [ { field: "examNumber", index: getFillAreaIndex("examNumber"), single: true, horizontal: false, items: listInfos, }, ], }; }, FILL_FIELD: (element) => { const dom = getPreviewElementById(element.id); return { info_area: [getOffsetInfo(dom)], }; }, FILL_TABLE: (element) => { const dom = getPreviewElementById(element.id); return { info_area: [getOffsetInfo(dom)], }; }, LINES: (element) => { const dom = getPreviewElementById(element.id); return { answer_area: [ { main_number: null, sub_number: null, area: getOffsetInfo(dom), }, ], }; }, GRIDS: (element) => { const dom = getPreviewElementById(element.id); return { answer_area: [ { main_number: null, sub_number: null, area: getOffsetInfo(dom), }, ], }; }, }; function getPageNumberInfo() { const dom = document.getElementById(`preview-page-box-0`); let options = []; dom .querySelector(".page-number-rect-list") .childNodes.forEach((item, index) => { options[index] = getOffsetInfo(item); }); return [ { field: "pageNumber", index: 1, single: true, horizontal: true, items: [ { main_number: null, sub_number: null, options, recog_info: [], }, ], }, ]; } function parsePageExchange(pages) { initFillAreaIndex(); const npages = deepCopy(pages); curPageOffsetInfo = document .getElementById(`preview-page-box-0`) .getBoundingClientRect(); const pageNumberInfo = pages.length > 2 ? getPageNumberInfo() : null; npages.forEach((page, pindex) => { curPageOffsetInfo = document .getElementById(`preview-page-box-${pindex}`) .getBoundingClientRect(); let exchange = { card_type: 2, page_size: page.pageSize, page_image: "", locator: elementInfoFunc.LOCATOR( document.getElementById(`preview-page-box-${pindex}`) ), 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 (!VALID_ELEMENTS_FOR_EXTERNAL.includes(element.type)) return; const info = elementInfoFunc[element.type](element); Object.entries(info).forEach(([key, vals]) => { exchange[key] = exchange[key].concat(vals); }); }); }); if (!(pindex % 2) && pageNumberInfo) { let pnoInfo = deepCopy(pageNumberInfo); pnoInfo[0].index = getFillAreaIndex("pageNumber"); exchange.fill_area = exchange.fill_area.concat(pnoInfo); } page.exchange = exchange; }); return npages; } export function getPageModel({ cardConfig, pages }) { let npages = parsePageExchange(pages); return JSON.stringify( { version: CARD_VERSION, cardType: "FREE", cardConfig, pages: npages, }, (k, v) => (k.startsWith("_") ? undefined : v) ); }