exchange.js 9.5 KB

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