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 }; 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) { let { offsetTop, offsetLeft } = dom; let parentNode = dom.offsetParent; while (parentNode.className.indexOf("page-box") === -1) { offsetTop += parentNode.offsetTop; offsetLeft += parentNode.offsetLeft; parentNode = parentNode.offsetParent; } const pw = parentNode.offsetWidth; const ph = parentNode.offsetHeight; const infos = [ offsetLeft / pw, offsetTop / ph, dom.offsetWidth / pw, dom.offsetHeight / ph ]; return infos.map(num => num.toFixed(10) * 1); } // locator: [], // barcode: [], // info_area: [], // fill_area: [], // answer_area: [] const elementInfoFunc = { LOCATOR: locators => { const tops = locators.top.map(locator => { return getOffsetInfo(document.getElementById(locator.id)); }); const bottoms = locators.bottom.map(locator => { return getOffsetInfo(document.getElementById(locator.id)); }); 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.querySelector(".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); const pageNumberInfo = pages.length > 2 ? getPageNumberInfo() : null; npages.forEach((page, pindex) => { let exchange = { card_type: 2, page_size: page.pageSize, page_image: "", locator: elementInfoFunc.LOCATOR(page.locators), 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, paperParams, pages }) { let npages = parsePageExchange(pages); return JSON.stringify( { version: CARD_VERSION, cardConfig, paperParams, pages: npages }, (k, v) => (k.startsWith("_") ? undefined : v) ); }