Ver Fonte

feat: 题卡页面新增课程代码条码

zhangjie há 11 meses atrás
pai
commit
03746b41f3

+ 23 - 0
card/assets/styles/card-preview.scss

@@ -349,6 +349,29 @@
   }
 }
 
+// course-barcode
+.course-barcode {
+  position: absolute;
+  width: 200px;
+  height: 40px;
+  top: 10px;
+  left: 50%;
+  margin-left: -200px;
+  text-align: center;
+
+  img {
+    display: block;
+    height: 28px;
+    width: 100%;
+    border: none;
+  }
+  p {
+    line-height: 1;
+    font-size: 12px;
+    margin: 0;
+  }
+}
+
 // elem
 .elem {
   &-title {

+ 59 - 0
card/assets/styles/card-temp.css

@@ -7,6 +7,7 @@
   margin: 10px auto;
   box-shadow: 0 0 4px #ddd;
 }
+
 .card-print {
   padding: 0;
 }
@@ -31,6 +32,7 @@
 .card-print .package-number {
   display: block !important;
 }
+
 .page-box {
   position: relative;
   background: #fff;
@@ -93,6 +95,7 @@
 .page-box-less .page-number-rect {
   display: none;
 }
+
 .page-main-inner {
   position: absolute;
   width: 100%;
@@ -103,6 +106,7 @@
   z-index: 9;
   font-size: 0;
 }
+
 .page-main-outer {
   position: absolute;
   top: 0;
@@ -113,6 +117,7 @@
   background-color: transparent;
   overflow: hidden;
 }
+
 .page-column {
   display: inline-block;
   vertical-align: middle;
@@ -205,6 +210,7 @@
   .element-item-card-head.element-item-type-pre::before {
   border-bottom: none;
 }
+
 .page-locator {
   position: absolute;
   left: 80px;
@@ -230,6 +236,7 @@
 .page-locator-item:nth-of-type(2) {
   right: 96px;
 }
+
 .page-box-1 .page-locator-bottom .page-locator-item:nth-of-type(1) {
   right: 0;
   left: auto;
@@ -240,6 +247,7 @@
 .page-box-1 .page-locator-item:nth-of-type(2) {
   right: 0;
 }
+
 .page-number {
   position: absolute;
   bottom: 30px;
@@ -271,9 +279,32 @@
   height: 16px;
   line-height: 16px;
 }
+
 .page-box-A4 .page-number-rect {
   left: 50%;
 }
+
+.course-barcode {
+  position: absolute;
+  width: 200px;
+  height: 40px;
+  top: 10px;
+  left: 50%;
+  margin-left: -200px;
+  text-align: center;
+}
+.course-barcode img {
+  display: block;
+  height: 28px;
+  width: 100%;
+  border: none;
+}
+.course-barcode p {
+  line-height: 1;
+  font-size: 12px;
+  margin: 0;
+}
+
 .elem-title {
   padding: 10px;
   font-size: 14px;
@@ -285,10 +316,12 @@
 .elem-body {
   padding: 10px;
 }
+
 .grid-container {
   margin-left: -10px;
   margin-right: -10px;
 }
+
 .grid-row {
   display: table;
   width: 100%;
@@ -308,6 +341,7 @@
   border-style: dashed;
   vertical-align: middle;
 }
+
 .card-head-top {
   text-align: center;
   color: #000;
@@ -704,6 +738,7 @@
 .card-head-handle.card-head-narrow .head-stdno {
   height: 242px;
 }
+
 .card-head-body-auto-resize {
   margin-left: -5px;
   margin-right: -5px;
@@ -736,6 +771,7 @@
   border: none;
   margin: 0 !important;
 }
+
 .elem-topic-head {
   text-align: center;
 }
@@ -763,6 +799,7 @@
   white-space: nowrap;
   overflow: hidden;
 }
+
 .elem-line-horizontal {
   height: 100%;
   line-height: 30px;
@@ -773,6 +810,7 @@
   width: 100%;
   border-bottom: 1px solid #000;
 }
+
 .elem-line-vertical {
   height: 100%;
   text-align: center;
@@ -783,10 +821,12 @@
   height: 100%;
   border-left: 1px solid #000;
 }
+
 .elem-lines .line-item {
   display: inline-block;
   vertical-align: top;
 }
+
 .elem-rect .rect-body {
   position: absolute;
   width: 100%;
@@ -794,6 +834,7 @@
   top: 0;
   left: 0;
 }
+
 .elem-text .text-body {
   padding: 5px;
   line-height: 1.4;
@@ -807,6 +848,7 @@
   color: #a0a0a0;
   margin: 0 2px;
 }
+
 .elem-barcode {
   height: 100%;
   border-color: transparent;
@@ -823,6 +865,7 @@
   right: 0;
   margin: auto;
 }
+
 .elem-image {
   height: 100%;
   border-color: transparent;
@@ -854,6 +897,7 @@
   right: 0;
   margin: auto;
 }
+
 .elem-grids > table {
   table-layout: fixed;
   border-spacing: 0;
@@ -869,9 +913,11 @@
 .elem-grids-halving td > div {
   padding-bottom: 100%;
 }
+
 .elem-pane {
   height: 100%;
 }
+
 .elem-fill-question {
   white-space: normal;
 }
@@ -977,6 +1023,7 @@
 .elem-fill-question-vertical .option-item:last-child {
   margin-bottom: 0 !important;
 }
+
 .elem-fill-area .option-item {
   display: inline-block;
   vertical-align: middle;
@@ -993,6 +1040,7 @@
 .elem-fill-area-vertical .option-item:last-child {
   margin-bottom: 0 !important;
 }
+
 .elem-fill-line {
   white-space: normal;
 }
@@ -1053,6 +1101,7 @@
   text-align: center;
   border: none;
 }
+
 .elem-explain .elem-title {
   padding-bottom: 0;
 }
@@ -1078,6 +1127,7 @@
 .elem-explain .elem-explain-element .explain-element-body {
   position: absolute;
 }
+
 .elem-composition .elem-title {
   padding-bottom: 0;
 }
@@ -1097,6 +1147,7 @@
   position: absolute;
   overflow: hidden;
 }
+
 .elem-fill-number {
   border: 1px solid #000;
 }
@@ -1149,10 +1200,12 @@
   transform: scale(0.67, 0.67);
   -webkit-transform: scale(0.67, 0.67);
 }
+
 .elem-fill-field {
   white-space: normal;
   overflow: hidden;
 }
+
 .fill-field-item {
   display: inline-block;
   padding: 0 10px;
@@ -1205,6 +1258,7 @@
   margin-left: 80px;
   height: 100%;
 }
+
 .elem-fill-pane {
   font-size: 0;
   white-space: normal;
@@ -1218,6 +1272,7 @@
 .elem-fill-pane .fill-pane-cont {
   border: 1px solid #000;
 }
+
 .elem-forbid-area {
   height: 100%;
   position: relative;
@@ -1232,6 +1287,7 @@
   font-size: 30px;
   text-align: center;
 }
+
 .elem-fill-table .table {
   width: 100%;
   border-spacing: 0;
@@ -1241,6 +1297,7 @@
 .elem-fill-table .table td {
   padding: 0;
 }
+
 .elem-undertaking {
   position: absolute;
   width: 60px;
@@ -1296,6 +1353,7 @@
   top: auto;
   left: 0;
 }
+
 .card-free-preview:not(.card-print) {
   padding: 10px 0;
   background-color: #f0f0f0;
@@ -1311,6 +1369,7 @@
 .card-free-preview .page-column-element .element-item::before {
   display: none;
 }
+
 @media print {
   .card-preview {
     padding: 0;

+ 11 - 1
card/components/CardDesign.vue

@@ -189,6 +189,10 @@
               v-if="cardConfig.undertakingEnable && pageNo === pages.length - 1"
               :content="cardConfig.undertakingBody"
             ></elem-undertaking>
+            <course-barcode
+              v-if="pageNo % 2 === 0"
+              :data="cardConfig"
+            ></course-barcode>
           </div>
         </div>
       </div>
@@ -264,6 +268,7 @@ import PageNumber from "../components/PageNumber";
 import CardHeadSample from "../elements/card-head/CardHead";
 import TopicSelectDialog from "../components/TopicSelectDialog";
 import ElemUndertaking from "../elements/undertaking/ElemUndertaking.vue";
+import CourseBarcode from "./CourseBarcode.vue";
 
 export default {
   name: "card-design",
@@ -294,6 +299,7 @@ export default {
     PageNumber,
     TopicSelectDialog,
     ElemUndertaking,
+    CourseBarcode,
   },
   data() {
     return {
@@ -535,7 +541,11 @@ export default {
       if (!this.checkCardValid()) return;
 
       this.$emit("on-submit", {
-        cardConfig: this.cardConfig,
+        cardConfig: {
+          ...this.cardConfig,
+          courseCodeBarcodeSrc: "",
+          courseCodeBarcodeName: "",
+        },
         pages: this.pages,
         answers: this.content.answers || {},
       });

+ 11 - 1
card/components/CardView.vue

@@ -81,6 +81,10 @@
             v-if="cardConfig.undertakingEnable && pageNo === pages.length - 1"
             :content="cardConfig.undertakingBody"
           ></elem-undertaking>
+          <course-barcode
+            v-if="pageNo % 2 === 0"
+            :data="cardConfig"
+          ></course-barcode>
         </div>
       </div>
     </template>
@@ -90,13 +94,19 @@
 <script>
 import TopicElementPreview from "./TopicElementPreview";
 import ElemUndertaking from "../elements/undertaking/ElemUndertaking.vue";
+import CourseBarcode from "./CourseBarcode.vue";
 import PageNumber from "./PageNumber";
 import previewTemp from "../previewTemp";
 import exchangeMixins from "../mixins/exchange";
 
 export default {
   name: "card-view",
-  components: { TopicElementPreview, PageNumber, ElemUndertaking },
+  components: {
+    TopicElementPreview,
+    PageNumber,
+    ElemUndertaking,
+    CourseBarcode,
+  },
   mixins: [exchangeMixins],
   props: {
     pages: {

+ 32 - 0
card/components/CourseBarcode.vue

@@ -0,0 +1,32 @@
+<template>
+  <div class="course-barcode">
+    <img
+      v-if="data.courseCodeBarcodeSrc"
+      :src="data.courseCodeBarcodeSrc"
+      :alt="data.courseCodeBarcodeName"
+    />
+    <img
+      v-else
+      src="../assets/images/barcode-sample-notext.png"
+      alt="课程代码条码"
+    />
+    <p>{{ data.courseCodeBarcodeName || "123456789" }}</p>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "course-barcode",
+  props: {
+    data: {
+      type: Object,
+      default() {
+        return { courseCodeBarcodeSrc: "", courseCodeBarcodeName: "" };
+      },
+    },
+  },
+  data() {
+    return {};
+  },
+};
+</script>

+ 11 - 1
card/modules/free/components/CardFreeDesign.vue

@@ -180,6 +180,10 @@
               :total="pages.length"
               :current="curPageNo + 1"
             ></page-number>
+            <course-barcode
+              v-if="curPageNo % 2 === 0"
+              :data="cardConfig"
+            ></course-barcode>
           </div>
         </div>
       </div>
@@ -220,6 +224,7 @@ import HelpDialog from "../components/HelpDialog";
 import EditPage from "../../../elements/page/EditPage";
 
 import PageNumber from "../../../components/PageNumber";
+import CourseBarcode from "../../../components/CourseBarcode.vue";
 
 export default {
   name: "card-free-design",
@@ -248,6 +253,7 @@ export default {
     ShortcutKey,
     HelpDialog,
     PageNumber,
+    CourseBarcode,
   },
   data() {
     return {
@@ -399,7 +405,11 @@ export default {
       }
 
       this.$emit("on-submit", {
-        cardConfig: this.cardConfig,
+        cardConfig: {
+          ...this.cardConfig,
+          courseCodeBarcodeSrc: "",
+          courseCodeBarcodeName: "",
+        },
         pages: this.pages,
       });
     },

+ 6 - 1
card/modules/free/components/CardFreeView.vue

@@ -77,6 +77,10 @@
             :total="pages.length"
             :current="pageNo + 1"
           ></page-number>
+          <course-barcode
+            v-if="pageNo % 2 === 0"
+            :data="cardConfig"
+          ></course-barcode>
         </div>
       </div>
     </template>
@@ -86,12 +90,13 @@
 <script>
 import TopicElementPreview from "./TopicElementPreview";
 import PageNumber from "../../../components/PageNumber";
+import CourseBarcode from "../../../components/CourseBarcode.vue";
 import previewTemp from "../../../previewTemp";
 import { getPageModel } from "../cardFormatTransform";
 
 export default {
   name: "card-free-view",
-  components: { TopicElementPreview, PageNumber },
+  components: { TopicElementPreview, PageNumber, CourseBarcode },
   props: {
     pages: {
       type: Array,

Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
card/previewTemp.js


+ 2 - 0
src/modules/card/components/CardBuildDialog.vue

@@ -292,6 +292,8 @@ export default {
           columnGap: 20,
           showForbidArea: false,
           makeMethod: "SELF",
+          courseCodeBarcodeSrc: "data:image/png;base64,${courseCodeBarcodeSrc}",
+          courseCodeBarcodeName: "${courseCodeBarcodeName}",
         },
       };
       config.fillNumber = data.examNumberDigit;

+ 19 - 0
src/modules/card/views/CardEdit.vue

@@ -31,6 +31,7 @@ import { examRuleDetail } from "../../base/api";
 import { getEnums } from "../../login/api";
 import timeMixin from "@/mixins/timeMixin";
 import { MD5 } from "@/plugins/md5";
+import { getBase64Barcode } from "@/plugins/utils";
 
 export default {
   name: "card-edit",
@@ -109,6 +110,13 @@ export default {
           cardConfig,
         };
       }
+
+      // 设置默认的课程代码条码信息
+      if (!this.cardContent.cardConfig.courseCodeBarcodeSrc) {
+        this.cardContent.cardConfig.courseCodeBarcodeSrc =
+          getBase64Barcode("123456789");
+        this.cardContent.cardConfig.courseCodeBarcodeName = "123456789";
+      }
       this.dataReady = true;
     },
     getCardTitle(titleRule) {
@@ -144,6 +152,13 @@ export default {
           cardConfig,
         };
       }
+
+      if (detData.courseCode) {
+        this.cardContent.cardConfig.courseCodeBarcodeSrc = getBase64Barcode(
+          detData.courseCode
+        );
+        this.cardContent.cardConfig.courseCodeBarcodeName = detData.courseCode;
+      }
     },
     async getCardConfig() {
       if (this.cardCreateMethod === "STANDARD") {
@@ -160,6 +175,8 @@ export default {
             columnGap: 20,
             showForbidArea: false,
             makeMethod: this.prepareTcPCard.makeMethod,
+            courseCodeBarcodeSrc: "",
+            courseCodeBarcodeName: "",
           },
         };
         config.fillNumber = data.examNumberDigit;
@@ -187,6 +204,8 @@ export default {
           columnGap: 20,
           showForbidArea: false,
           requiredFields,
+          courseCodeBarcodeSrc: "",
+          courseCodeBarcodeName: "",
           extendFields: JSON.parse(extendFields),
         };
         return config;

+ 15 - 18
src/modules/card/views/CardPreview.vue

@@ -17,8 +17,7 @@
 import CardView from "../../../../card/components/CardView";
 import CardFreeView from "../../../../card/modules/free/components/CardFreeView";
 import { cardDetail } from "../api";
-import { deepCopy } from "@/plugins/utils";
-const JsBarcode = require("jsbarcode");
+import { deepCopy, getBase64Barcode } from "@/plugins/utils";
 
 export default {
   name: "card-preview",
@@ -99,6 +98,13 @@ export default {
           fieldInfos.paperTypeName = "${paperTypeName}";
         }
       }
+      // 保存题卡时,清除src,使用占位字符,以便后台使用变量填充
+      // 编辑预览题卡时,则使用给定内容
+      if (!cardConfig.courseCodeBarcodeSrc) {
+        cardConfig.courseCodeBarcodeSrc =
+          "data:image/png;base64,${courseCodeBarcodeSrc}";
+        cardConfig.courseCodeBarcodeName = "${courseCodeBarcodeName}";
+      }
 
       this.cardConfig = cardConfig;
       this.pages = this.appendFieldInfo(pages, fieldInfos);
@@ -145,6 +151,11 @@ export default {
       const { cardConfig, pages } = JSON.parse(detData.content);
       const fieldInfos = this.fetchFieldInfos(cardConfig, {});
 
+      if (detData.courseCode) {
+        cardConfig.courseCodeBarcodeSrc = getBase64Barcode(detData.courseCode);
+        cardConfig.courseCodeBarcodeName = detData.courseCode;
+      }
+
       this.cardConfig = cardConfig;
       this.pages = this.appendFieldInfo(pages, fieldInfos);
     },
@@ -173,13 +184,13 @@ export default {
         });
       if (this.cardCreateMethod === "STANDARD") {
         if (isPrintExamNumber) {
-          fieldInfos.examNumber = this.getBase64Barcode(
+          fieldInfos.examNumber = getBase64Barcode(
             stdInfo["examNumber"] || defNumber
           );
           fieldInfos.examNumberStr = stdInfo["examNumber"] || defNumber;
         }
         if (cardConfig.aOrB && cardConfig.paperType === "PRINT") {
-          fieldInfos.paperType = this.getBase64Barcode(
+          fieldInfos.paperType = getBase64Barcode(
             stdInfo["paperType"] || defNumber
           );
           fieldInfos.paperTypeName = stdInfo["paperTypeName"] || "A";
@@ -188,20 +199,6 @@ export default {
 
       return fieldInfos;
     },
-    getBase64Barcode(str) {
-      const canvas = document.createElement("CANVAS");
-      JsBarcode(canvas, str, {
-        width: 2,
-        height: 30,
-        displayValue: false,
-        marginLeft: 20,
-        marginRight: 20,
-        marginTop: 0,
-        marginBottom: 0,
-      });
-
-      return canvas.toDataURL();
-    },
     appendFieldInfo(pages, fieldInfos) {
       if (this.cardCreateMethod === "STANDARD") {
         pages.forEach((page, pageNo) => {

+ 3 - 17
src/modules/card/views/CardRulePreview.vue

@@ -14,7 +14,7 @@
 import CardView from "../../../../card/components/CardView";
 import { getNewPage, getCardHeadModel } from "../../../../card/elementModel";
 import { cardConfigInfos } from "../api";
-const JsBarcode = require("jsbarcode");
+import { getBase64Barcode } from "@/plugins/utils";
 
 export default {
   name: "card-rule-preview",
@@ -87,13 +87,13 @@ export default {
             : "";
         });
       if (isPrintExamNumber) {
-        fieldInfos.examNumber = this.getBase64Barcode(
+        fieldInfos.examNumber = getBase64Barcode(
           stdInfo["examNumber"] || defNumber
         );
         fieldInfos.examNumberStr = stdInfo["examNumber"] || defNumber;
       }
       if (cardConfig.aOrB && cardConfig.paperType === "PRINT") {
-        fieldInfos.paperType = this.getBase64Barcode(
+        fieldInfos.paperType = getBase64Barcode(
           stdInfo["paperType"] || defNumber
         );
         fieldInfos.paperTypeName = stdInfo["paperTypeName"] || "A";
@@ -101,20 +101,6 @@ export default {
 
       return fieldInfos;
     },
-    getBase64Barcode(str) {
-      const canvas = document.createElement("CANVAS");
-      JsBarcode(canvas, str, {
-        width: 2,
-        height: 30,
-        displayValue: false,
-        marginLeft: 20,
-        marginRight: 20,
-        marginTop: 0,
-        marginBottom: 0,
-      });
-
-      return canvas.toDataURL();
-    },
   },
 };
 </script>

+ 16 - 0
src/plugins/utils.js

@@ -1,4 +1,5 @@
 const deepmerge = require("deepmerge");
+const JsBarcode = require("jsbarcode");
 
 /**
  * 判断对象类型
@@ -497,3 +498,18 @@ export function toPrecision(num, fractionDigits) {
 export function listFilterEmpty(list) {
   return list.filter((item) => item || item === 0);
 }
+
+export function getBase64Barcode(str) {
+  const canvas = document.createElement("CANVAS");
+  JsBarcode(canvas, str, {
+    width: 2,
+    height: 28,
+    displayValue: false,
+    marginLeft: 10,
+    marginRight: 10,
+    marginTop: 1,
+    marginBottom: 1,
+  });
+
+  return canvas.toDataURL();
+}

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff