cardFormatTransform.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  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: this.getLocatorInfo(page.locators),
  51. // barcode: [],
  52. // info_area: [],
  53. // fill_area: [],
  54. // answer_area: []
  55. const elementInfoFunc = {
  56. LOCATOR: locators => {
  57. const result = locators.map(locatorGroup => {
  58. const locatorInfos = locatorGroup.map(locator => {
  59. return getOffsetInfo(document.getElementById(locator.id));
  60. });
  61. return {
  62. top: locatorInfos[0],
  63. bottom: locatorInfos[1]
  64. };
  65. });
  66. return {
  67. locator: result
  68. };
  69. },
  70. BARCODE: element => {
  71. return {
  72. barcode: [
  73. {
  74. field: element.field,
  75. area: getOffsetInfo(getPreviewElementById(element.id))
  76. }
  77. ]
  78. };
  79. },
  80. FILL_QUESTION: element => {
  81. const dom = getPreviewElementById(element.id);
  82. const single = !element.isMultiply;
  83. const horizontal = element.optionDirection === "horizontal";
  84. let fillAreas = [];
  85. dom.querySelectorAll(".group-item").forEach(groupItem => {
  86. let listInfos = [];
  87. groupItem
  88. .querySelectorAll(".question-item")
  89. .forEach((questionItem, questionIndex) => {
  90. let options = [];
  91. questionItem.childNodes.forEach((optionItem, optionIndex) => {
  92. if (optionIndex)
  93. options[optionIndex - 1] = this.getOffsetInfo(optionItem);
  94. });
  95. listInfos[questionIndex] = {
  96. main_number: element.topicNo,
  97. sub_number: questionItem.firstChild.textContent * 1,
  98. options
  99. };
  100. });
  101. fillAreas.push({
  102. field: "question",
  103. index: getFillAreaIndex("question"),
  104. single,
  105. horizontal,
  106. items: listInfos
  107. });
  108. });
  109. return {
  110. fill_area: fillAreas
  111. };
  112. },
  113. FILL_LINE: element => {
  114. const dom = getPreviewElementById(element.id);
  115. let sub_numbers = [];
  116. for (
  117. let i = element.startNumber,
  118. len = element.startNumber + element.questionsCount;
  119. i < len;
  120. i++
  121. ) {
  122. sub_numbers.push(i);
  123. }
  124. return {
  125. answer_area: [
  126. {
  127. main_number: element.topicNo,
  128. sub_numbers,
  129. area: getOffsetInfo(dom)
  130. }
  131. ]
  132. };
  133. },
  134. FILL_NUMBER: element => {
  135. let listInfos = [];
  136. const dom = getPreviewElementById(element.id);
  137. dom
  138. .querySelectorAll(".fill-number-list")
  139. .forEach((questionItem, questionIndex) => {
  140. let options = [];
  141. questionItem.childNodes.forEach((optionItem, optionIndex) => {
  142. options[optionIndex] = getOffsetInfo(optionItem);
  143. });
  144. listInfos[questionIndex] = {
  145. main_number: null,
  146. sub_number: null,
  147. options
  148. };
  149. });
  150. return {
  151. fill_area: [
  152. {
  153. field: "examNumber",
  154. index: getFillAreaIndex("examNumber"),
  155. single: true,
  156. horizontal: false,
  157. items: listInfos
  158. }
  159. ]
  160. };
  161. },
  162. FILL_FIELD: element => {
  163. const dom = getPreviewElementById(element.id);
  164. return {
  165. info_area: [getOffsetInfo(dom)]
  166. };
  167. },
  168. FILL_TABLE: element => {
  169. const dom = getPreviewElementById(element.id);
  170. return {
  171. info_area: [getOffsetInfo(dom)]
  172. };
  173. },
  174. LINES: element => {
  175. const dom = getPreviewElementById(element.id);
  176. return {
  177. answer_area: [
  178. {
  179. main_number: null,
  180. sub_numbers: null,
  181. area: getOffsetInfo(dom)
  182. }
  183. ]
  184. };
  185. },
  186. GRIDS: element => {
  187. const dom = getPreviewElementById(element.id);
  188. return {
  189. answer_area: [
  190. {
  191. main_number: null,
  192. sub_numbers: null,
  193. area: getOffsetInfo(dom)
  194. }
  195. ]
  196. };
  197. }
  198. };
  199. function getPageNumberInfo() {
  200. const dom = document.querySelector(".page-box-0");
  201. let options = [];
  202. dom
  203. .querySelector(".page-number-rect-list")
  204. .childNodes.forEach((item, index) => {
  205. options[index] = this.getOffsetInfo(item);
  206. });
  207. return [
  208. {
  209. field: "pageNumber",
  210. index: 1,
  211. single: true,
  212. horizontal: true,
  213. items: [
  214. {
  215. main_number: null,
  216. sub_number: null,
  217. options
  218. }
  219. ]
  220. }
  221. ];
  222. }
  223. function parsePageExchange(pages) {
  224. initFillAreaIndex();
  225. const npages = deepCopy(pages);
  226. const pageNumberInfo = getPageNumberInfo();
  227. npages.forEach((page, pindex) => {
  228. let exchange = {
  229. locator: elementInfoFunc.LOCATOR(page.locators),
  230. barcode: [],
  231. info_area: [],
  232. fill_area: [],
  233. answer_area: []
  234. };
  235. const elements = [
  236. page.globals,
  237. ...page.columns.map(column => column.elements)
  238. ];
  239. elements.forEach(elemGroup => {
  240. elemGroup.forEach(element => {
  241. if (!VALID_ELEMENTS_FOR_EXTERNAL.includes(element.type)) return;
  242. const info = elementInfoFunc[element.typ](element);
  243. Object.entries(info).forEach(([key, vals]) => {
  244. exchange[key] = exchange[key].concat(vals);
  245. });
  246. });
  247. });
  248. if (!(pindex % 2)) {
  249. let pnoInfo = deepCopy(pageNumberInfo);
  250. pnoInfo[0].index = getFillAreaIndex("pageNumber");
  251. exchange.fill_area = exchange.fill_area.concat(pnoInfo);
  252. }
  253. page.exchange = exchange;
  254. });
  255. return npages;
  256. }
  257. export function getPageModel({ cardConfig, paperParams, pages }) {
  258. let npages = parsePageExchange(pages);
  259. npages.forEach(page => {
  260. page.exchange.page_size = cardConfig.pageSize;
  261. });
  262. return JSON.stringify(
  263. {
  264. version: CARD_VERSION,
  265. cardConfig,
  266. paperParams,
  267. pages: npages
  268. },
  269. (k, v) => (k.startsWith("_") ? undefined : v)
  270. );
  271. }
  272. // TODO:缺考涂填
  273. // export default {
  274. // methods: {
  275. // getCardHeadInfo(element) {
  276. // const dom = this.getPreviewElementById(element.id);
  277. // const headArea = this.getOffsetInfo(dom);
  278. // let fill_area = [];
  279. // let barcode = [];
  280. // // 缺考涂填
  281. // if (element.examAbsent && !element.isSimple) {
  282. // fill_area.push({
  283. // field: "absent",
  284. // index: this.getFillAreaIndex("absent"),
  285. // single: true,
  286. // horizontal: true,
  287. // items: [
  288. // {
  289. // main_number: null,
  290. // sub_number: null,
  291. // options: [
  292. // this.getOffsetInfo(document.getElementById("dynamic-miss-area"))
  293. // ]
  294. // }
  295. // ]
  296. // });
  297. // }
  298. // // A/B卷类型
  299. // if (element.aOrB && !element.isSimple) {
  300. // // fill_area
  301. // let options = [];
  302. // document
  303. // .getElementById("head-dynamic-aorb")
  304. // .querySelectorAll(".head-dynamic-rect")
  305. // .forEach((optionItem, optionIndex) => {
  306. // options[optionIndex] = this.getOffsetInfo(optionItem);
  307. // });
  308. // fill_area.push({
  309. // field: "paperType",
  310. // index: this.getFillAreaIndex("paperType"),
  311. // single: true,
  312. // horizontal: true,
  313. // items: [
  314. // {
  315. // main_number: null,
  316. // sub_number: null,
  317. // options
  318. // }
  319. // ]
  320. // });
  321. // }
  322. // return {
  323. // info_area: [headArea],
  324. // fill_area,
  325. // barcode
  326. // };
  327. // }
  328. // }
  329. // };