Pārlūkot izejas kodu

分装二维码生成组件、引入url加密

Joe 3 gadi atpakaļ
vecāks
revīzija
99daeeea69

+ 1 - 0
package.json

@@ -46,6 +46,7 @@
     "element-ui": "2.13.2",
     "file-saver": "2.0.1",
     "fuse.js": "3.4.4",
+    "html2canvas": "^1.1.4",
     "jquery": "^3.5.1",
     "js-beautify": "1.10.2",
     "js-cookie": "2.2.0",

+ 123 - 0
src/components/QrCode/index.vue

@@ -0,0 +1,123 @@
+<template>
+  <div>
+    <div style="color: #97a8be; font-size: 12px; text-align: center">
+      点击图片进行下载
+    </div>
+    <div @click="downloadImg()" style="text-align: center" id="qrDiv">
+      <vue-qr :text="text" :margin="0" :size="400" class="d-block mx-auto" />
+      <slot></slot>
+    </div>
+  </div>
+</template>
+
+<script>
+import { scrollTo } from "@/utils/scroll-to";
+import vueQr from "vue-qr";
+import html2canvas from "html2canvas";
+
+export default {
+  name: "QrCode",
+  props: {
+    page: {
+      type: Number,
+      default: 1,
+    },
+    limit: {
+      type: Number,
+      default: 10,
+    },
+    pageSizes: {
+      type: Array,
+      default() {
+        return [10, 20, 30, 50];
+      },
+    },
+    layout: {
+      type: String,
+      default: "total, sizes, prev, pager, next, jumper",
+    },
+    background: {
+      type: Boolean,
+      default: true,
+    },
+    autoScroll: {
+      type: Boolean,
+      default: true,
+    },
+    hidden: {
+      type: Boolean,
+      default: false,
+    },
+    pagerCount: {
+      type: Number,
+      default: 7,
+    },
+    text: {
+      type: String,
+      required: true,
+    },
+    name:{
+      type: String,
+      required: true,
+    }
+  },
+  components: {
+    vueQr,
+  },
+  computed: {
+    currentPage: {
+      get() {
+        return this.page;
+      },
+      set(val) {
+        this.$emit("update:page", val);
+      },
+    },
+    pageSize: {
+      get() {
+        return this.limit;
+      },
+      set(val) {
+        this.$emit("update:limit", val);
+      },
+    },
+  },
+  methods: {
+    downloadImg() {
+      try {
+        html2canvas(document.getElementById("qrDiv"), {
+          allowTaint: false,
+        }).then((canvas) => {
+          const a = document.createElement("a");
+          const event = new MouseEvent("click");
+          a.download = this.name;
+          a.href = canvas.toDataURL();
+          a.dispatchEvent(event);
+          this.$emit("downloadImg")
+        });
+      } catch (error) {
+        this.msgError("导出二维码失败,请刷新重试~")
+      }
+    },
+    exportQr(text) {
+      this.text = "https://goto.huijy.net/" + this.deptId + "/" + trimEqualStr;
+      this.exportQrDialog = true;
+    },
+    handleSizeChange(val) {
+      this.$emit("pagination", { page: this.currentPage, limit: val });
+      if (this.autoScroll) {
+        scrollTo(0, 800);
+      }
+    },
+    handleCurrentChange(val) {
+      this.$emit("pagination", { page: val, limit: this.pageSize });
+      if (this.autoScroll) {
+        scrollTo(0, 800);
+      }
+    },
+  },
+};
+</script>
+
+<style scoped>
+</style>

+ 104 - 0
src/utils/base64.js

@@ -0,0 +1,104 @@
+export default class Base64 {  
+   
+  // private property  
+  _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";  
+ 
+  // public method for encoding  
+  encode = function (input) {  
+      var output = "";  
+      var chr1, chr2, chr3, enc1, enc2, enc3, enc4;  
+      var i = 0;  
+      input = this._utf8_encode(input);  
+      while (i < input.length) {  
+          chr1 = input.charCodeAt(i++);  
+          chr2 = input.charCodeAt(i++);  
+          chr3 = input.charCodeAt(i++);  
+          enc1 = chr1 >> 2;  
+          enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);  
+          enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);  
+          enc4 = chr3 & 63;  
+          if (isNaN(chr2)) {  
+              enc3 = enc4 = 64;  
+          } else if (isNaN(chr3)) {  
+              enc4 = 64;  
+          }  
+          output = output +  
+          this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +  
+          this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);  
+      }  
+      return output;  
+  }  
+ 
+  // public method for decoding  
+  decode = function (input) {  
+      var output = "";  
+      var chr1, chr2, chr3;  
+      var enc1, enc2, enc3, enc4;  
+      var i = 0;  
+      input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");  
+      while (i < input.length) {  
+          enc1 = this._keyStr.indexOf(input.charAt(i++));  
+          enc2 = this._keyStr.indexOf(input.charAt(i++));  
+          enc3 = this._keyStr.indexOf(input.charAt(i++));  
+          enc4 = this._keyStr.indexOf(input.charAt(i++));  
+          chr1 = (enc1 << 2) | (enc2 >> 4);  
+          chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);  
+          chr3 = ((enc3 & 3) << 6) | enc4;  
+          output = output + String.fromCharCode(chr1);  
+          if (enc3 != 64) {  
+              output = output + String.fromCharCode(chr2);  
+          }  
+          if (enc4 != 64) {  
+              output = output + String.fromCharCode(chr3);  
+          }  
+      }  
+      output = this._utf8_decode(output);  
+      return output;  
+  }  
+ 
+  // private method for UTF-8 encoding  
+  _utf8_encode(string) {  
+      string = string.replace(/\r\n/g,"\n");  
+      var utftext = "";  
+      for (var n = 0; n < string.length; n++) {  
+          var c = string.charCodeAt(n);  
+          if (c < 128) {  
+              utftext += String.fromCharCode(c);  
+          } else if((c > 127) && (c < 2048)) {  
+              utftext += String.fromCharCode((c >> 6) | 192);  
+              utftext += String.fromCharCode((c & 63) | 128);  
+          } else {  
+              utftext += String.fromCharCode((c >> 12) | 224);  
+              utftext += String.fromCharCode(((c >> 6) & 63) | 128);  
+              utftext += String.fromCharCode((c & 63) | 128);  
+          }  
+ 
+      }  
+      return utftext;  
+  }  
+ 
+  // private method for UTF-8 decoding  
+  _utf8_decode(utftext) {  
+
+      let [string, i, c, c1, c2, c3] = ['', 0, 0, 0, 0, 0]
+      
+      while ( i < utftext.length ) {  
+          c = utftext.charCodeAt(i);  
+          if (c < 128) {  
+              string += String.fromCharCode(c);  
+              i++;  
+          } else if((c > 191) && (c < 224)) {  
+              c2 = utftext.charCodeAt(i+1);  
+
+              string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));  
+              i += 2;  
+          } else {  
+              c2 = utftext.charCodeAt(i+1);  
+              c3 = utftext.charCodeAt(i+2);  
+              string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));  
+              i += 3;  
+          }  
+      }  
+      return string;  
+  }  
+}

+ 19 - 17
src/views/label/Label_AddLabel.vue

@@ -53,7 +53,7 @@
           您没有添加标签,所以标签功能尚未生效
         </el-form-item>
       </div>
-      <div v-if="labelForm.labelFlag == 1" >
+      <div v-if="labelForm.labelFlag == 1">
         <el-form-item
           v-for="(label, index) in labelForm.labelArr"
           :label="'标签' + (index + 1)"
@@ -118,15 +118,15 @@
     </el-form>
 
     <el-dialog
-      :visible.sync="exportDialog"
+      :visible.sync="exportQrDialog"
       width="700px"
       append-to-body
       title="导出标签"
     >
-      <div 
+      <div
         @click="downloadImg()"
-        class="d-block mx-auto" 
-        style="width:600px"
+        class="d-block mx-auto"
+        style="width: 600px;text-align: center;"
         id="qrDiv"
       >
         <vue-qr
@@ -134,17 +134,16 @@
           text="http://qrcode.html"
           :margin="10"
           :size="500"
-          
         />
         <div>你好</div>
       </div>
-
     </el-dialog>
   </div>
 </template>
 <script>
 import { sysDeptDemoList, addlabel, selectLabel } from "@/api/label/label";
 import vueQr from 'vue-qr'
+import html2canvas from 'html2canvas';
 
 export default {
   name: "Label_AddLabel",
@@ -163,7 +162,7 @@ export default {
       editable: true,
       tempForm: undefined,
       pageStatus: 0,
-      exportDialog: false
+      exportQrDialog: false
     };
   },
   components: {
@@ -267,16 +266,19 @@ export default {
       this.editable = !this.editable;
     },
     exportPayCode(){
-      this.exportDialog = true;
+      this.exportQrDialog = true;
     },
-    downloadImg(link_id) {
-        html2canvas(document.getElementById('qrDiv'), {
-            onrendered: function(ca) {
-                // $('#saveImages').attr('src',ca.toDataURL('image/jpeg'));
-                console.log(ca);
-            }
-        });
-      // const iconUrl = this.$refs['Qrcode'].$el.src
+    downloadImg() {
+      html2canvas(document.getElementById('qrDiv'), {allowTaint: true}).then(canvas => {
+          const a = document.createElement('a')
+          const event = new MouseEvent('click')
+          console.log()
+          a.download = '标签支付码'
+          a.href = canvas.toDataURL() 
+          a.dispatchEvent(event)
+      });
+
+      // // const iconUrl = this.$refs['Qrcode'].$el.src
       // const a = document.createElement('a')
       // const event = new MouseEvent('click')
       // console.log()

+ 115 - 18
src/views/station/Station_Employee.vue

@@ -22,7 +22,11 @@
         >
       </el-form-item>
     </el-form>
-    <div class="mt-5" style="text-align: center" v-if="personnelList.length==0">
+    <div
+      class="mt-5"
+      style="text-align: center"
+      v-if="personnelList.length == 0"
+    >
       请至少添加一名加油员,否则小程序无法进行支付~
     </div>
     <el-table :data="personnelList" v-else>
@@ -45,6 +49,7 @@
         label="操作"
         align="center"
         class-name="small-padding fixed-width"
+        width="200"
       >
         <template slot-scope="scope">
           <el-button
@@ -61,6 +66,13 @@
             @click="handleDelete(scope.row)"
             >删除</el-button
           >
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-download"
+            @click="exportQr(scope.row)"
+            >导出加油员码</el-button
+          >
         </template>
       </el-table-column>
     </el-table>
@@ -76,7 +88,10 @@
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
         <el-form-item label="姓名" prop="personnelName">
-          <el-input v-model="form.personnelName" placeholder="请输入加油员姓名" />
+          <el-input
+            v-model="form.personnelName"
+            placeholder="请输入加油员姓名"
+          />
         </el-form-item>
         <el-form-item label="负责枪号" prop="checkedGunList">
           <template v-if="allGunList.length === 0">
@@ -109,7 +124,13 @@
     </el-dialog>
 
     <el-dialog
-      :title="personnelList.length == 0 ? '添加加油员须知' : personnelList.length == 1 ? '添加加油员确认' : '删除加油员确认'"
+      :title="
+        personnelList.length == 0
+          ? '添加加油员须知'
+          : personnelList.length == 1
+          ? '添加加油员确认'
+          : '删除加油员确认'
+      "
       :visible.sync="confirmDialog"
       width="500px"
       append-to-body
@@ -120,10 +141,15 @@
           1、请至少添加一名加油员,否则小程序无法进行支付。
         </div>
         <div style="color: red; font-size: 12px; text-indent: 2em" class="mt-2">
-          2、当您只添加 【<b>一名加油员</b>】 :小程序采取开放模式(即用户<b>可以不通过扫加油员码进入</b>),小程序会拉取该加油员所管理的油枪,用户产生的订单全部算在该加油员的名下。
+          2、当您只添加 【<b>一名加油员</b>】
+          :小程序采取开放模式(即用户<b>可以不通过扫加油员码进入</b>),小程序会拉取该加油员所管理的油枪,用户产生的订单全部算在该加油员的名下。
         </div>
-        <div style="color: red; font-size: 12px; text-indent: 2em" class="mt-2 mb-3">
-          3、当您添加了 【<b>多名加油员</b>】 :小程序采取限制模式(即<b>只能够通过扫加油员码进入</b>),小程序会拉取对应加油员码下的加油员所管理的油枪,用户扫加油员码产生的订单算在对应加油员的名下。
+        <div
+          style="color: red; font-size: 12px; text-indent: 2em"
+          class="mt-2 mb-3"
+        >
+          3、当您添加了 【<b>多名加油员</b>】
+          :小程序采取限制模式(即<b>只能够通过扫加油员码进入</b>),小程序会拉取对应加油员码下的加油员所管理的油枪,用户扫加油员码产生的订单算在对应加油员的名下。
         </div>
       </div>
       <div class="m-2" v-else-if="personnelList.length == 1">
@@ -151,7 +177,9 @@
       </div>
       <div class="m-2" v-else-if="personnelList.length == 2">
         <div>您目前有两名加油员,订单会根据加油员码计入加油员名下。</div>
-        <div>您正在删除一名加油员,操作成功之后,<b>系统将发生以下变化:</b></div>
+        <div>
+          您正在删除一名加油员,操作成功之后,<b>系统将发生以下变化:</b>
+        </div>
         <div style="color: red; font-size: 12px; text-indent: 2em" class="mt-4">
           1、小程序端会开放用户进入的方式,用户可以通过多种方式进入小程序进行支付。
         </div>
@@ -169,11 +197,16 @@
 
       <div slot="footer" class="dialog-footer">
         <el-button
-          :type="personnelList.length == 0 || personnelList.length == 1 ? 'primary' : 'danger'"
+          :type="
+            personnelList.length == 0 || personnelList.length == 1
+              ? 'primary'
+              : 'danger'
+          "
           @click="confirmSubmit"
           >{{
-            personnelList.length == 0 ? '我知道了~':
-            personnelList.length == 1
+            personnelList.length == 0
+              ? "我知道了~"
+              : personnelList.length == 1
               ? "我已经了解,继续添加加油员"
               : "我已经了解,确认删除该加油员"
           }}</el-button
@@ -181,6 +214,24 @@
         <el-button @click="confirmCancel">取 消</el-button>
       </div>
     </el-dialog>
+
+    <el-dialog
+      :visible.sync="exportQrDialog"
+      width="600px"
+      append-to-body
+      title="导出标签"
+    >
+      <div>
+        <qr text="121111" @downloadImg="downloadImg" name="员工码">
+          <div>员工码:{{ this.currentExport.personnelName }}</div>
+          <div >负责枪号: 
+            <span v-for="ele in currentExport.checkedGunList" :key="ele">
+                {{ ele + '号枪-' + transferGunnumToOilname(ele) + "  "}}
+            </span>
+          </div>
+        </qr>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
@@ -195,6 +246,10 @@ import {
 } from "@/api/station/personnel";
 import { stationinfo, listGun } from "@/api/station/gun";
 import { getDept } from "@/api/system/dept";
+import Base64 from "@/utils/base64";
+import vueQr from "vue-qr";
+import qr from "@/components/QrCode";
+
 export default {
   name: "Station_Employee",
   data() {
@@ -240,13 +295,27 @@ export default {
       pageStatus: 0,
       confirmDialog: false,
       deletePersonnelId: undefined,
+      exportQrDialog: false,
+      qrStr: "",
+      currentExport: {},
     };
   },
+  components: {
+    vueQr,
+    qr,
+  },
   created() {
+    const base = new Base64();
+    const a = base.encode("12李哈哈");
+    console.log("加密", a);
+    console.log("解密", base.decode(a));
     this.init();
     this.setPageStatus();
   },
   methods: {
+    downloadImg() {
+      this.msgSuccess("导出成功~");
+    },
     /** 查询油站加油员信息列表 */
     getList() {
       listPersonnel(this.queryParams).then((response) => {
@@ -286,6 +355,7 @@ export default {
         stationId: this.deptId,
       }).then((response) => {
         this.allGunList = response.rows;
+        console.log('this.allGunList',this.allGunList);
       });
     },
     // 取消按钮
@@ -365,21 +435,22 @@ export default {
       this.deletePersonnelId = row.personnelId;
       if (this.personnelList.length == 2) {
         this.confirmDialog = true;
-
         return;
       }
       this.$confirm("是否确认删除油站加油员信息", "警告", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning",
-      }).then( ()=> {
+      }).then(() => {
         console.log(123);
-        delPersonnel(this.deletePersonnelId).then(() => {
-          this.getList();
-          this.msgSuccess("删除成功~");
-        }).catch(() => {
-          this.msgError("删除失败~");
-        });
+        delPersonnel(this.deletePersonnelId)
+          .then(() => {
+            this.getList();
+            this.msgSuccess("删除成功~");
+          })
+          .catch(() => {
+            this.msgError("删除失败~");
+          });
       });
     },
     /** 导出按钮操作 */
@@ -397,6 +468,32 @@ export default {
           this.download(response.msg);
         });
     },
+    exportQr(row) {
+      this.currentExport = JSON.parse(JSON.stringify(row));
+      if (row.gunNo !== null) {
+        this.currentExport.checkedGunList = [
+          ...new Set(row.gunNo.split(",")),
+        ].filter((ele) => {
+          return ele.toString().trim() !== "";
+        });
+      } else {
+        this.currentExport.checkedGunList = [];
+      }
+
+      const base = new Base64();
+      const encodeStr = "e" + row.personnelId + "/";
+      const encodedStr = base.encode(encodeStr);
+      const trimEqualStr = encodedStr.replace(/={1,}$/g, "");
+      console.log(base.decode(trimEqualStr));
+      this.qrStr = "https://goto.huijy.net/" + this.deptId + "/" + trimEqualStr;
+      this.exportQrDialog = true;
+    },
+    transferGunnumToOilname(gunNo){
+      const gun = this.allGunList.find((ele)=>{
+        return ele.oilGunNo == gunNo;
+      })
+      return gun.oilName
+    }
   },
 };
 </script>