cardFormatTransform.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. import { CARD_VERSION } from "../../enumerate";
  2. import { deepCopy } from "../../plugins/utils";
  3. const initIndex = {
  4. question: 1,
  5. absent: 1,
  6. paperType: 1,
  7. examNumber: 1,
  8. selective: 1,
  9. pageNumber: 1
  10. };
  11. let fillAreaIndex = { ...initIndex };
  12. const VALID_ELEMENTS_FOR_EXTERNAL = [
  13. "LOCATOR",
  14. "BARCODE",
  15. "FILL_QUESTION",
  16. "FILL_LINE",
  17. "FILL_NUMBER",
  18. "FILL_FIELD",
  19. "FILL_TABLE",
  20. "LINES",
  21. "GRIDS"
  22. ];
  23. function initFillAreaIndex() {
  24. fillAreaIndex = { ...initIndex };
  25. }
  26. function getFillAreaIndex(type) {
  27. return fillAreaIndex[type]++;
  28. }
  29. function getPreviewElementById(id) {
  30. return document.getElementById(`preview-${id}`);
  31. }
  32. function getOffsetInfo(dom) {
  33. let { offsetTop, offsetLeft } = dom;
  34. let parentNode = dom.offsetParent;
  35. while (parentNode.className.indexOf("page-box") === -1) {
  36. offsetTop += parentNode.offsetTop;
  37. offsetLeft += parentNode.offsetLeft;
  38. parentNode = parentNode.offsetParent;
  39. }
  40. const pw = parentNode.offsetWidth;
  41. const ph = parentNode.offsetHeight;
  42. const infos = [
  43. offsetLeft / pw,
  44. offsetTop / ph,
  45. dom.offsetWidth / pw,
  46. dom.offsetHeight / ph
  47. ];
  48. return infos.map(num => num.toFixed(10) * 1);
  49. }
  50. // locator: [],
  51. // barcode: [],
  52. // info_area: [],
  53. // fill_area: [],
  54. // answer_area: []
  55. const elementInfoFunc = {
  56. LOCATOR: locators => {
  57. const tops = locators.top.map(locator => {
  58. return getOffsetInfo(document.getElementById(locator.id));
  59. });
  60. const bottoms = locators.bottom.map(locator => {
  61. return getOffsetInfo(document.getElementById(locator.id));
  62. });
  63. return { top: tops, bottom: bottoms };
  64. },
  65. BARCODE: element => {
  66. return {
  67. barcode: [
  68. {
  69. field: element.field,
  70. area: getOffsetInfo(getPreviewElementById(element.id))
  71. }
  72. ]
  73. };
  74. },
  75. FILL_QUESTION: element => {
  76. const dom = getPreviewElementById(element.id);
  77. const single = !element.isMultiply;
  78. const horizontal = element.optionDirection === "horizontal";
  79. let fillAreas = [];
  80. dom.querySelectorAll(".group-item").forEach(groupItem => {
  81. let listInfos = [];
  82. groupItem
  83. .querySelectorAll(".question-item")
  84. .forEach((questionItem, questionIndex) => {
  85. let options = [];
  86. questionItem.childNodes.forEach((optionItem, optionIndex) => {
  87. if (optionIndex)
  88. options[optionIndex - 1] = getOffsetInfo(optionItem);
  89. });
  90. listInfos[questionIndex] = {
  91. main_number: element.topicNo,
  92. sub_number: questionItem.firstChild.textContent * 1,
  93. options,
  94. recog_info: []
  95. };
  96. });
  97. fillAreas.push({
  98. field: "question",
  99. index: getFillAreaIndex("question"),
  100. single,
  101. horizontal,
  102. items: listInfos
  103. });
  104. });
  105. return {
  106. fill_area: fillAreas
  107. };
  108. },
  109. FILL_LINE: element => {
  110. const dom = getPreviewElementById(element.id);
  111. let sub_numbers = [];
  112. for (
  113. let i = element.startNumber,
  114. len = element.startNumber + element.questionsCount;
  115. i < len;
  116. i++
  117. ) {
  118. sub_numbers.push(i);
  119. }
  120. return {
  121. answer_area: [
  122. {
  123. main_number: element.topicNo,
  124. sub_number: sub_numbers.join(),
  125. area: getOffsetInfo(dom)
  126. }
  127. ]
  128. };
  129. },
  130. FILL_NUMBER: element => {
  131. let listInfos = [];
  132. const dom = getPreviewElementById(element.id);
  133. dom
  134. .querySelectorAll(".fill-number-list")
  135. .forEach((questionItem, questionIndex) => {
  136. let options = [];
  137. questionItem.childNodes.forEach((optionItem, optionIndex) => {
  138. options[optionIndex] = getOffsetInfo(optionItem);
  139. });
  140. listInfos[questionIndex] = {
  141. main_number: null,
  142. sub_number: null,
  143. options,
  144. recog_info: []
  145. };
  146. });
  147. return {
  148. fill_area: [
  149. {
  150. field: "examNumber",
  151. index: getFillAreaIndex("examNumber"),
  152. single: true,
  153. horizontal: false,
  154. items: listInfos
  155. }
  156. ]
  157. };
  158. },
  159. FILL_FIELD: element => {
  160. const dom = getPreviewElementById(element.id);
  161. return {
  162. info_area: [getOffsetInfo(dom)]
  163. };
  164. },
  165. FILL_TABLE: element => {
  166. const dom = getPreviewElementById(element.id);
  167. return {
  168. info_area: [getOffsetInfo(dom)]
  169. };
  170. },
  171. LINES: element => {
  172. const dom = getPreviewElementById(element.id);
  173. return {
  174. answer_area: [
  175. {
  176. main_number: null,
  177. sub_number: null,
  178. area: getOffsetInfo(dom)
  179. }
  180. ]
  181. };
  182. },
  183. GRIDS: element => {
  184. const dom = getPreviewElementById(element.id);
  185. return {
  186. answer_area: [
  187. {
  188. main_number: null,
  189. sub_number: null,
  190. area: getOffsetInfo(dom)
  191. }
  192. ]
  193. };
  194. }
  195. };
  196. function getPageNumberInfo() {
  197. const dom = document.querySelector(".page-box-0");
  198. let options = [];
  199. dom
  200. .querySelector(".page-number-rect-list")
  201. .childNodes.forEach((item, index) => {
  202. options[index] = getOffsetInfo(item);
  203. });
  204. return [
  205. {
  206. field: "pageNumber",
  207. index: 1,
  208. single: true,
  209. horizontal: true,
  210. items: [
  211. {
  212. main_number: null,
  213. sub_number: null,
  214. options,
  215. recog_info: []
  216. }
  217. ]
  218. }
  219. ];
  220. }
  221. function parsePageExchange(pages) {
  222. initFillAreaIndex();
  223. const npages = deepCopy(pages);
  224. const pageNumberInfo = pages.length > 2 ? getPageNumberInfo() : null;
  225. npages.forEach((page, pindex) => {
  226. let exchange = {
  227. card_type: 2,
  228. page_size: page.pageSize,
  229. page_image: "",
  230. locator: elementInfoFunc.LOCATOR(page.locators),
  231. fill_locator: [],
  232. check_area: {
  233. black_line: [],
  234. white_line: []
  235. },
  236. barcode: [],
  237. qrcode: [],
  238. ocr_area: [],
  239. info_area: [],
  240. fill_area: [],
  241. answer_area: [],
  242. extension: {
  243. barcode: [],
  244. fill_area: [],
  245. ocr_area: [],
  246. qrcode: []
  247. }
  248. };
  249. const elements = [
  250. page.globals,
  251. ...page.columns.map(column => column.elements)
  252. ];
  253. elements.forEach(elemGroup => {
  254. elemGroup.forEach(element => {
  255. if (!VALID_ELEMENTS_FOR_EXTERNAL.includes(element.type)) return;
  256. const info = elementInfoFunc[element.type](element);
  257. Object.entries(info).forEach(([key, vals]) => {
  258. exchange[key] = exchange[key].concat(vals);
  259. });
  260. });
  261. });
  262. if (!(pindex % 2) && pageNumberInfo) {
  263. let pnoInfo = deepCopy(pageNumberInfo);
  264. pnoInfo[0].index = getFillAreaIndex("pageNumber");
  265. exchange.fill_area = exchange.fill_area.concat(pnoInfo);
  266. }
  267. page.exchange = exchange;
  268. });
  269. return npages;
  270. }
  271. export function getPageModel({ cardConfig, paperParams, pages }) {
  272. let npages = parsePageExchange(pages);
  273. return JSON.stringify(
  274. {
  275. version: CARD_VERSION,
  276. cardConfig,
  277. paperParams,
  278. pages: npages
  279. },
  280. (k, v) => (k.startsWith("_") ? undefined : v)
  281. );
  282. }