123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- <template>
- <my-modal
- v-model:open="visible"
- title="导入卡格式"
- :width="600"
- @ok="submitHandle"
- >
- <qm-low-form
- :params="params"
- :fields="fields"
- :label-width="110"
- :rules="rules"
- ref="form"
- >
- <template #file>
- <ImportButton @fileChange="getFile" />
- </template>
- <template #subjectCode>
- <SelectSubject
- v-model="params.subjectCode"
- :exam-id="userStore.curExam?.id"
- ></SelectSubject>
- </template>
- </qm-low-form>
- </my-modal>
- </template>
- <script name="ImportCardDialog" lang="ts" setup>
- import { ref, reactive, computed } from "vue";
- import { importCard } from "@/ap/baseDataConfig";
- import { useUserStore } from "@/store";
- import SelectSubject from "@/components/SelectSubject/index.vue";
- const userStore = useUserStore();
- const form = ref();
- const visible = defineModel();
- const emit = defineEmits(["success"]);
- const params = reactive({
- subjectCode: "",
- remark: "",
- file: null,
- paperCount: void 0,
- singlePage: false,
- dpi: 150,
- });
- const cardJson = ref(null);
- const fields = computed(() => {
- return [
- {
- prop: "subjectCode",
- cell: "subjectCode",
- label: "科目题卡",
- colSpan: 24,
- },
- {
- prop: "remark",
- type: "textarea",
- label: "备注",
- colSpan: 24,
- attrs: {
- spellcheck: "false",
- },
- },
- { prop: "file", cell: "file", label: "选择卡格式", colSpan: 24 },
- {
- prop: "paperCount",
- type: "number",
- label: "张数",
- colSpan: 24,
- attrs: { min: 1 },
- },
- {
- prop: "singlePage",
- type: "radio",
- label: "单页题卡",
- colSpan: 24,
- attrs: {
- options: [
- { value: false, label: "否" },
- { value: true, label: "是" },
- ],
- },
- },
- params.file && isJson.value && cardJson.value && !cardJson.value.dpi
- ? {
- prop: "dpi",
- type: "radio",
- label: "DPI",
- colSpan: 24,
- attrs: {
- options: [
- { value: 150, label: "150" },
- { value: 200, label: "200" },
- ],
- disabled: cardJson.value?.dpi,
- onChange: () => {
- compareSize();
- },
- },
- }
- : null,
- ];
- });
- const isJson = ref(true);
- const cardSizePass = ref(true);
- const isJsonString = (str: string) => {
- try {
- const toObj = JSON.parse(str);
- if (toObj && typeof toObj === "object") {
- return true;
- }
- } catch {}
- return false;
- };
- const rules = {
- subjectCode: [{ required: true, message: "请选择科目" }],
- file: [
- { required: true, message: "请上传文件" },
- {
- validator: async () => {
- if (!isJson) {
- return Promise.reject("卡格式json文件内容异常,请检查");
- } else {
- if (cardJson.value && !cardSizePass.value) {
- return Promise.reject("卡格式图片dpi异常!");
- } else {
- return Promise.resolve();
- }
- }
- },
- },
- ],
- paperCount: [
- { required: true, message: "请输入张数" },
- {
- validator: async (rule: any, value: any) => {
- if (cardJson.value) {
- if (
- (params.singlePage && cardJson.value.pages.length != value) ||
- (!params.singlePage && cardJson.value.pages.length / 2 != value)
- ) {
- return Promise.reject("张数未校验通过,请检查!");
- } else {
- return Promise.resolve();
- }
- } else {
- return Promise.resolve();
- }
- },
- },
- ],
- dpi: [
- {
- validator: async () => {
- if (!isJson) {
- return Promise.reject("卡格式json文件内容异常,请检查");
- } else {
- if (cardJson.value && !cardSizePass.value) {
- return Promise.reject("卡格式图片dpi异常!");
- } else {
- return Promise.resolve();
- }
- }
- },
- },
- ],
- };
- let pageSizeStr = "";
- let contentRecord: any = null;
- let imgRecord: any = null;
- const compareSize = () => {
- let target = contentRecord?.[pageSizeStr];
- let w = imgRecord?.width / params.dpi / 0.0394;
- let h = imgRecord?.height / params.dpi / 0.0394;
- if (Math.abs(w - target.width) > 10 || Math.abs(h - target.height) > 10) {
- cardSizePass.value = false;
- } else {
- cardSizePass.value = true;
- }
- };
- const validateCardSize = async (json: any) => {
- if (!json.pages.length) {
- cardSizePass.value = false;
- window.$message.error("卡格式文件里的pages为空");
- return;
- }
- window.electronApi?.getPageSizeIni((content: any) => {
- console.log(content);
- const img = new Image();
- img.onload = () => {
- pageSizeStr = json.pages[0].exchange["page_size"];
- contentRecord = content;
- imgRecord = img;
- compareSize();
- };
- img.onerror = function () {
- window.$message.error("卡格式json文件里的图片base64无效!");
- };
- img.src = "data:image/jpg;base64," + json.pages[0].exchange["page_image"];
- });
- };
- const getCardJsonContent = async (file: any) => {
- const reader = new FileReader();
- reader.onload = function (e) {
- try {
- const json = JSON.parse(e.target.result);
- console.log("json", json);
- cardJson.value = json;
- if (json.dpi) {
- params.dpi = Number(json.dpi);
- }
- validateCardSize(json);
- } catch (error) {
- console.error("Error parsing JSON:", error);
- isJson.value = false;
- }
- };
- reader.onerror = function (error) {
- console.error("File could not be read:", error);
- };
- reader.readAsText(file);
- };
- const getFile = (file: any) => {
- params.file = file;
- getCardJsonContent(file);
- };
- const submitHandle = () => {
- form.value.formRef.validate().then(() => {
- importCard({ examId: userStore.curExam?.id, ...params }).then(() => {
- emit("success");
- window.$message.success("导入成功");
- visible.value = false;
- });
- });
- };
- </script>
- <style lang="less" scoped></style>
|