ImportCardDialog.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <template>
  2. <my-modal
  3. v-model:open="visible"
  4. title="导入卡格式"
  5. :width="600"
  6. @ok="submitHandle"
  7. >
  8. <qm-low-form
  9. :params="params"
  10. :fields="fields"
  11. :label-width="110"
  12. :rules="rules"
  13. ref="form"
  14. >
  15. <template #file>
  16. <ImportButton @fileChange="getFile" />
  17. </template>
  18. <template #subjectCode>
  19. <SelectSubject
  20. v-model="params.subjectCode"
  21. :exam-id="userStore.curExam?.id"
  22. ></SelectSubject>
  23. </template>
  24. </qm-low-form>
  25. </my-modal>
  26. </template>
  27. <script name="ImportCardDialog" lang="ts" setup>
  28. import { ref, reactive, computed } from "vue";
  29. import { importCard } from "@/ap/baseDataConfig";
  30. import { useUserStore } from "@/store";
  31. import SelectSubject from "@/components/SelectSubject/index.vue";
  32. const userStore = useUserStore();
  33. const form = ref();
  34. const visible = defineModel();
  35. const emit = defineEmits(["success"]);
  36. const params = reactive({
  37. subjectCode: "",
  38. remark: "",
  39. file: null,
  40. paperCount: void 0,
  41. singlePage: false,
  42. dpi: 150,
  43. });
  44. const cardJson = ref(null);
  45. const fields = computed(() => {
  46. return [
  47. {
  48. prop: "subjectCode",
  49. cell: "subjectCode",
  50. label: "科目题卡",
  51. colSpan: 24,
  52. },
  53. {
  54. prop: "remark",
  55. type: "textarea",
  56. label: "备注",
  57. colSpan: 24,
  58. attrs: {
  59. spellcheck: "false",
  60. },
  61. },
  62. { prop: "file", cell: "file", label: "选择卡格式", colSpan: 24 },
  63. {
  64. prop: "paperCount",
  65. type: "number",
  66. label: "张数",
  67. colSpan: 24,
  68. attrs: { min: 1 },
  69. },
  70. {
  71. prop: "singlePage",
  72. type: "radio",
  73. label: "单页题卡",
  74. colSpan: 24,
  75. attrs: {
  76. options: [
  77. { value: false, label: "否" },
  78. { value: true, label: "是" },
  79. ],
  80. },
  81. },
  82. params.file && isJson.value && cardJson.value && !cardJson.value.dpi
  83. ? {
  84. prop: "dpi",
  85. type: "radio",
  86. label: "DPI",
  87. colSpan: 24,
  88. attrs: {
  89. options: [
  90. { value: 150, label: "150" },
  91. { value: 200, label: "200" },
  92. ],
  93. disabled: cardJson.value?.dpi,
  94. onChange: () => {
  95. compareSize();
  96. },
  97. },
  98. }
  99. : null,
  100. ];
  101. });
  102. const isJson = ref(true);
  103. const cardSizePass = ref(true);
  104. const isJsonString = (str: string) => {
  105. try {
  106. const toObj = JSON.parse(str);
  107. if (toObj && typeof toObj === "object") {
  108. return true;
  109. }
  110. } catch {}
  111. return false;
  112. };
  113. const rules = {
  114. subjectCode: [{ required: true, message: "请选择科目" }],
  115. file: [
  116. { required: true, message: "请上传文件" },
  117. {
  118. validator: async () => {
  119. if (!isJson) {
  120. return Promise.reject("卡格式json文件内容异常,请检查");
  121. } else {
  122. if (cardJson.value && !cardSizePass.value) {
  123. return Promise.reject("卡格式图片dpi异常!");
  124. } else {
  125. return Promise.resolve();
  126. }
  127. }
  128. },
  129. },
  130. ],
  131. paperCount: [
  132. { required: true, message: "请输入张数" },
  133. {
  134. validator: async (rule: any, value: any) => {
  135. if (cardJson.value) {
  136. if (
  137. (params.singlePage && cardJson.value.pages.length != value) ||
  138. (!params.singlePage && cardJson.value.pages.length / 2 != value)
  139. ) {
  140. return Promise.reject("张数未校验通过,请检查!");
  141. } else {
  142. return Promise.resolve();
  143. }
  144. } else {
  145. return Promise.resolve();
  146. }
  147. },
  148. },
  149. ],
  150. dpi: [
  151. {
  152. validator: async () => {
  153. if (!isJson) {
  154. return Promise.reject("卡格式json文件内容异常,请检查");
  155. } else {
  156. if (cardJson.value && !cardSizePass.value) {
  157. return Promise.reject("卡格式图片dpi异常!");
  158. } else {
  159. return Promise.resolve();
  160. }
  161. }
  162. },
  163. },
  164. ],
  165. };
  166. let pageSizeStr = "";
  167. let contentRecord: any = null;
  168. let imgRecord: any = null;
  169. const compareSize = () => {
  170. let target = contentRecord?.[pageSizeStr];
  171. let w = imgRecord?.width / params.dpi / 0.0394;
  172. let h = imgRecord?.height / params.dpi / 0.0394;
  173. if (Math.abs(w - target.width) > 10 || Math.abs(h - target.height) > 10) {
  174. cardSizePass.value = false;
  175. } else {
  176. cardSizePass.value = true;
  177. }
  178. };
  179. const validateCardSize = async (json: any) => {
  180. if (!json.pages.length) {
  181. cardSizePass.value = false;
  182. window.$message.error("卡格式文件里的pages为空");
  183. return;
  184. }
  185. window.electronApi?.getPageSizeIni((content: any) => {
  186. console.log(content);
  187. const img = new Image();
  188. img.onload = () => {
  189. pageSizeStr = json.pages[0].exchange["page_size"];
  190. contentRecord = content;
  191. imgRecord = img;
  192. compareSize();
  193. };
  194. img.onerror = function () {
  195. window.$message.error("卡格式json文件里的图片base64无效!");
  196. };
  197. img.src = "data:image/jpg;base64," + json.pages[0].exchange["page_image"];
  198. });
  199. };
  200. const getCardJsonContent = async (file: any) => {
  201. const reader = new FileReader();
  202. reader.onload = function (e) {
  203. try {
  204. const json = JSON.parse(e.target.result);
  205. console.log("json", json);
  206. cardJson.value = json;
  207. if (json.dpi) {
  208. params.dpi = Number(json.dpi);
  209. }
  210. validateCardSize(json);
  211. } catch (error) {
  212. console.error("Error parsing JSON:", error);
  213. isJson.value = false;
  214. }
  215. };
  216. reader.onerror = function (error) {
  217. console.error("File could not be read:", error);
  218. };
  219. reader.readAsText(file);
  220. };
  221. const getFile = (file: any) => {
  222. params.file = file;
  223. getCardJsonContent(file);
  224. };
  225. const submitHandle = () => {
  226. form.value.formRef.validate().then(() => {
  227. importCard({ examId: userStore.curExam?.id, ...params }).then(() => {
  228. emit("success");
  229. window.$message.success("导入成功");
  230. visible.value = false;
  231. });
  232. });
  233. };
  234. </script>
  235. <style lang="less" scoped></style>