exchange.js 9.4 KB

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