Browse Source

miniCert生成的特殊码

刘琳琳 1 week ago
parent
commit
adbc3d95af

+ 67 - 18
app.js

@@ -1,18 +1,8 @@
-import {
-  tracking,
-  snConfig,
-  getVisitDeviceUser,
-  publicInterface
-} from './utils/api/api'
-import {
-  getForm,
-  getDate,
-  formatTime
-} from './utils/index/index'
+import {getVisitDeviceUser, publicInterface, QRCodeQuery, snConfig, tracking} from './utils/api/api'
+import {getForm} from './utils/index/index'
+
+import {closeSecondaryScreen, openCycleSecondaryScreen, openSecondaryScreen} from './utils/index/callAmpe'
 
-import {
-  closeSecondaryScreen, openCycleSecondaryScreen, openSecondaryScreen
-} from './utils/index/callAmpe'
 App({
   data: {
     // 用户输入身份证号
@@ -274,14 +264,18 @@ App({
   scanCode() {
     my.on('initQRListener', async res => {
       console.log('⼆维码监听 ', res.data)
-      // 扫码登记
-      if (res.data && res.data.qrCode && res.data.qrCode.indexOf('HHFKJ') > -1) {
+      let specialCodeSwitch = this.globalData.snDisposition.specialCodeSwitch || false;
+      let specialCodePrefix = this.globalData.snDisposition.specialCodePrefix || '';
+      if (res.data && res.data.qrCode && res.data.qrCode.indexOf('HHFKJ') > -1) { // 扫码登记
         if (!this.data.isOkQrCodeSignIn) {
           this.data.isOkQrCodeSignIn = true
           let data = getForm(res.data.qrCode)
-          this.getVisitDeviceUser(data)
+          await this.getVisitDeviceUser(data)
         }
-      } else if (res.data && res.data.qrCode) {
+      } else if (specialCodeSwitch && res.data && res.data.qrCode && res.data.qrCode.indexOf(specialCodePrefix) > -1) { // 特殊码换三要素
+        let content = res.data;
+        await this.specialCodeUrlCheck(content)
+      } else if (res.data && res.data.qrCode) { // 扫码签离
         if (res.data.qrCode.indexOf('\\000026') > -1 || res.data.qrCode.indexOf('\\000029') > -1) {
           res.data.qrCode = res.data.qrCode.slice(7)
         }
@@ -323,6 +317,53 @@ App({
       }
     })
   },
+  /**
+   * 特殊码换三要素扫码登记
+   * @param content
+   * @returns {Promise<void>}
+   */
+  async specialCodeUrlCheck(content) {
+    console.log(content)
+    let specialCodeUrl = this.globalData.snDisposition.specialCodeUrl || '';
+    let specialCodeTimeout = this.globalData.snDisposition.specialCodeTimeout || 5;
+    let specialCodeFailedTips = this.globalData.snDisposition.specialCodeFailedTips || '特殊码换三要素接口请求超时';
+    let specialCodeTimeoutTips = this.globalData.snDisposition.specialCodeTimeoutTips || '特殊码换三要素接口请求失败';
+    try {
+      let res = await QRCodeQuery({
+        // specialCodeUrl: 'http://192.168.77.15:8109/hanghui-openapi/v1/proof/user/info/query',
+        specialCodeUrl,
+        specialCodeTimeout,
+        specialCodeFailedTips,
+        specialCodeTimeoutTips
+      }, content);
+      console.log('特殊码换三要素扫码登记', res)
+      let resultData = res.data || {};
+      let extInfo = JSON.parse(resultData.extInfo || '')
+      // this.data.userInfo.avatar = resultData.avatar
+      this.data.userInfo.idCardPhoto = resultData.photoBase64 || '';
+      this.data.userInfo.xm = resultData.certName || '';
+      this.data.userInfo.sfzh = resultData.certNo || '';
+      this.data.userInfo.phone = resultData.phone || '';
+      this.data.userInfo.visitorUnit = extInfo.visitorUnit || '';
+      this.data.userInfo.carnum = extInfo.carnum || '';
+      this.data.userInfo.verifyType = 5; // 二维码1:1
+      this.data.brushingCardUserIInfo = {
+        name: resultData.certName || '',
+        idNum: resultData.certNo || '',
+        photoBase64: resultData.photoBase64 || '',
+      }
+      my.reLaunch({
+        url: '/pages/resultPage/index?result=1:1比对&type=二维码1:1',
+      })
+    } catch (error) {
+      console.log(error)
+      let resultPageTimeout = this.globalData.snDisposition.resultPageTimeout || 5;
+      my.reLaunch({
+        url: '/pages/resultPage/index?result=失败&timer=' + resultPageTimeout + '&resultText=请重试',
+      })
+      return
+    }
+  },
   // 小程序二维码登记
   async getVisitDeviceUser(data) {
     let data1 = {
@@ -410,6 +451,14 @@ App({
       fkjSignOutUrl: "https://tx.hz-hanghui.com:8088/yx-fyzd/visitorSignOut", //手动签离
       transitPushSwitch: true, // 启用进出记录推送 默认值:true
       transitPushUrl: "https://tx.hz-hanghui.com:8088/yx-fyzd/visitorReport",
+
+      specialCodeSwitch: false, // 启用特殊码换三要素接口 默认值:false
+      specialCodeUrl: '', // 特殊码换三要素接口地址
+      specialCodeTimeout: 5, // 特殊码换三要素接口超时时间(s) TODO ADD_FIELD
+      specialCodeTimeoutTips: '特殊码换三要素接口请求超时', // 特殊码换三要素接口超时提示语 TODO ADD_FIELD
+      specialCodeFailedTips: '特殊码换三要素接口请求失败', // 特殊码换三要素接口失败提示语 TODO ADD_FIELD
+      specialCodePrefix: '', // 二维码标识(首位) TODO ADD_FIELD
+
       printVisitorList: false,
       signOut: true,
       riskCheck: false,

+ 5 - 6
pages/home/index.acss

@@ -73,15 +73,15 @@
 }
 
 .scan-code {
-  width: 318.75rpx;
-  height: 102.54rpx;
+  width: 200rpx;
+  height: 102rpx;
   background: url('https://tx.hz-hanghui.com:8088/yx-fyzd/file/upload/imagesnew/static/result//border.png') no-repeat;
   background-size: 100% 100%;
   background-attachment: fixed;
   position: absolute;
   right: 24rpx;
   bottom: 5rpx;
-  padding: 13rpx 18rpx;
+  padding: 13rpx 20rpx;
   box-sizing: border-box;
   justify-content: space-between;
 }
@@ -104,12 +104,11 @@
 .tip-text {
   font-size: 14rpx;
   color: #0E384D;
-  padding: 0 20rpx;
-  text-align: center;
   line-height: 25rpx;
   /*margin-top: 10rpx;*/
   display: flex;
-  align-items: center;
+  flex-direction: column;
+  justify-content: center;
 }
 
 .blod {

+ 6 - 12
pages/home/index.axml

@@ -9,7 +9,7 @@
           class="tab flex2 magnify"
           a:key="index"
           onTap="goto"
-          data-item={{item}}
+          data-item="{{item}}"
         >
           <image class="tab-icon" mode="scaleToFill" src="{{item.img}}" />
           <view>{{item.tit}}</view>
@@ -35,21 +35,15 @@
       </view>
     </view>
     <view
-      a:if="{{ snDisposition.wxScanRegister ||snDisposition.zfbScanRegister }}"
+      a:if="{{ snDisposition.wxScanRegister }}"
       class="scan-code flex1"
     >
-
-      <view a:if="{{snDisposition.zfbScanRegister  }}" class="qrcode-box">
-        <text>支付宝</text>
-        <image mode="scaleToFill" src="{{qrImgZFB}}" class="qrcode" data-src="{{qrImgZFB}}" />
-      </view>
       <view class="tip-text">
-        未携带身份证,手机扫码登记
-        <!--<text class="blod blue">,支持支付宝</text> 、<text class="blod">微信</text> 扫码 -->
+        <view>未携带身份证</view>
+        <view>手机微信扫码</view>
       </view>
-      <view a:if="{{ snDisposition.wxScanRegister }}" class="qrcode-box">
-        <text>微信</text>
-        <image mode="scaleToFill" src="{{qrImgWX}}" class="qrcode" data-src="{{qrImgWX}}" />
+      <view class="qrcode-box">
+        <image mode="scaleToFill" src="{{qrCodeImg}}" class="qrcode" data-src="{{qrCodeImg}}" />
       </view>
     </view>
     <bottom-parnel suerName="确定" onSure="sure" isHomePage="{{true}}" showBtn="{{false}}" />

+ 40 - 11
pages/home/index.js

@@ -1,16 +1,13 @@
 import {
   snConfig,
-  getVisitDeviceUser
+  getWXScanQRCodeValue,
+  createWXScanQRCode
 } from '../../utils/api/api'
 import {
   getQRCodeUrl,
-  getForm,
   getWaterDrop,
-  throttle,
+  throttle,guid
 } from '../../utils/index/index'
-import {
-  receiptPrinting
-} from '../../utils/index/receiptPrinting'
 import { closeSecondaryScreen, openSecondaryScreen } from "../../utils/index/callAmpe";
 const app = getApp()
 Page({
@@ -62,8 +59,8 @@ Page({
     },
     ],
     centerListCope: [],
-    qrImgWX: '', // 微信二维码图片地址
-    qrImgZFB: '', // 支付宝二维码图片地址
+    qrCodeImg: '', // 微信二维码图片地址
+    qrCodeUrl: '', // 微信二维码 码值
     intervalId: null, //定时器
     intervalId1: null, //定时器
   },
@@ -100,6 +97,7 @@ Page({
     app.globalData.riskResult = 1
     app.data.isNetworkQueryError = true
     app.data.clickRetryNum = 0
+    console.log('clickRetryNum', app.data.clickRetryNum)
   },
   clickAudio() {
     getWaterDrop()
@@ -138,10 +136,41 @@ Page({
         qrImgWX
       })
     }
-    if (app.globalData.snDisposition.zfbQrcodeUrl) {
-      let qrImgZFB = await getQRCodeUrl(app.globalData.snDisposition.zfbQrcodeUrl)
+    if (app.globalData.snDisposition.wxScanRegister) {
+      let info = {
+        connectionId: `${guid()}`,
+        extInfo: [{
+          keyName: "carnum",
+          keyboardType: "carNumber",
+          placeholder: "请选择车牌",
+          title: "车牌",
+          type: "",
+          value: ""
+        }, {
+          keyName: "visitorUnit",
+          keyboardType: "text",
+          placeholder: "请输入单位",
+          title: "单位",
+          type: "",
+          value: ""
+        }], // 额外填写信息
+        mode: 'http', // websocket(长链接)/http(三要素换特殊码)
+        needCertName: true, // 姓名
+        needCertNo: true, // 证件号
+        needPhone: false, // 手机号
+        needPhotoBase64: false, // 	照片
+        needReal: false, // 是否需要实名比对
+        sn: app.globalData.sn, // 设备sn
+      }
+      let res = await getWXScanQRCodeValue(info);
+      let qrCodeUrl = `https://tx.hz-hanghui.com:8088?connectionId=${res.data.connectionId || ''}&encryptId=${res.data.encryptId || ''}&sn=${app.globalData.sn || ''}&mode=http`
+      // let qrCodeUrl = `https://test.hz-hanghui.com:18890?connectionId=${res.data.connectionId || ''}&encryptId=${res.data.encryptId || ''}&sn=${app.globalData.sn || ''}&mode=http`;
+      let qrRes = await createWXScanQRCode({ qrcodeContent: qrCodeUrl, width: 300, height: 300 });
+      let qrCodeImg = qrRes.data.qrcodeUrl || '';
+      // let qrCodeImg = await getQRCodeUrl(qrCodeUrl)
       this.setData({
-        qrImgZFB
+        qrCodeUrl,
+        qrCodeImg
       })
     }
   },

+ 6 - 15
pages/inputIDCard/index.js

@@ -1,17 +1,9 @@
-import {
-  isCardID,
-  getWaterDrop
-} from '../../utils/index/index'
-import {
-  userInfoQuery
-} from '../../utils/api/api'
-import {
-  encryptAndSign
-} from '../../utils/index/getSM4'
+import {getWaterDrop, isCardID} from '../../utils/index/index'
+import {userInfoQuery} from '../../utils/api/api'
+import {encryptAndSign} from '../../utils/index/getSM4'
+
+import {viceBroadcast} from '../../utils/index/callAmpe'
 
-import {
-  viceBroadcast
-} from '../../utils/index/callAmpe'
 const app = getApp()
 Page({
   data: {
@@ -140,12 +132,11 @@ Page({
         return
       }
       let decrypted = JSON.parse(decryptedData.decrypted)
-      let brushingCardUserIInfo = {
+      app.data.brushingCardUserIInfo = {
         name: decrypted.xm,
         idNum: decrypted.sfzh,
         photoBase64: decrypted.xp,
       }
-      app.data.brushingCardUserIInfo = brushingCardUserIInfo
       app.data.userInfo = decrypted
       app.data.userInfo.avatar = decrypted.xp
       app.data.userInfo.idCardPhoto = decrypted.xp

+ 11 - 10
pages/interviewee/index.js

@@ -203,6 +203,7 @@ Page({
     let visitReasonList = (app.globalData.snDisposition.visitReason || '业务拜访/会议邀请/施工单位/其他事项').split('/');
     console.log(JSON.stringify(app.globalData.snDisposition))
     console.log(JSON.stringify(app.globalData.registerNotDesensitizedColumn))
+    console.log('phone', app.data.userInfo.phone, app.data.inputPhone)
     this.setData({
       snDisposition: app.globalData.snDisposition,
       causeMatterList: visitReasonList,
@@ -383,8 +384,8 @@ Page({
             ...item.info2
           }
         })
-        return { 
-          ...item, 
+        return {
+          ...item,
           info1:{
             ...item.info1,
             isSel: !item.info1.isSel // 切换选中状态
@@ -393,11 +394,11 @@ Page({
             ...item.info2,
             isSel: !item.info2.isSel // 切换选中状态
           }
-         }; 
+         };
       }
       return item; // 其他项保持不变
     });
-    this.setData({ 
+    this.setData({
       historyList: items,
     }); // 更新数据状态
   },
@@ -436,12 +437,12 @@ Page({
             ...item.info1,
             isSel: !item.info1.isSel // 切换选中状态
           }
-         }; 
+         };
       }
       return item; // 其他项保持不变
     });
     this.setData({
-      historyList: items 
+      historyList: items
     }); // 更新数据状态
   },
   defaultFormInfo(){
@@ -485,12 +486,12 @@ Page({
             ...item.info2,
             isSel: !item.info2.isSel // 切换选中状态
           }
-         }; 
+         };
       }
       return item; // 其他项保持不变
     });
-    this.setData({ 
-      historyList: items 
+    this.setData({
+      historyList: items
     }); // 更新数据状态
   },
   backEnter(){
@@ -809,7 +810,7 @@ Page({
       carnum
     } = this.data
     let form = Object.assign({}, remainingInfo, intervieweeForm);
-    console.log('form --->', form) 
+    console.log('form --->', form)
     form.carnum = carnum
     form.visitingTime = getDate()
     app.data.visitoMsgData = form

+ 15 - 27
pages/resultPage/index.js

@@ -1,22 +1,9 @@
-import {
-  closeSecondaryScreen,
-  openCycleSecondaryScreen,
-  openSecondaryScreen,
-  viceBroadcast
-} from '../../utils/index/callAmpe'
-import {
-  receiptPrinting
-} from '../../utils/index/receiptPrinting'
-import {
-  encryptAndSign
-} from '../../utils/index/getSM4'
-import {
-  desensitization,
-  getWaterDrop
-} from '../../utils/index/index'
-import {
-  userInfoQuery,
-} from '../../utils/api/api'
+import {closeSecondaryScreen, openSecondaryScreen, viceBroadcast} from '../../utils/index/callAmpe'
+import {receiptPrinting} from '../../utils/index/receiptPrinting'
+import {encryptAndSign} from '../../utils/index/getSM4'
+import {desensitization, getWaterDrop} from '../../utils/index/index'
+import {userInfoQuery,} from '../../utils/api/api'
+
 const app = getApp()
 Page({
   data: {
@@ -67,6 +54,9 @@ Page({
         case '手输1:1':
           verifyType = 15;
           break;
+        case '二维码1:1':
+          verifyType = 5;
+          break;
       }
       this.setData({
         showFaceScan: true,
@@ -161,7 +151,7 @@ Page({
         my.hideLoading()
         that.data.showFaceScan = false
         if (res.success && res.data.idNum) {
-          let form = {
+          app.data.userInfo = {
             xm: res.data.name,
             sfzh: res.data.idNum,
             phone: res.data.mobile,
@@ -169,7 +159,6 @@ Page({
             verifyType: 2, // 支付宝人脸
             certContent: res.data // 身份证阅读器返回全部
           }
-          app.data.userInfo = form
           viceBroadcast(app.globalData.snDisposition.successVoice)
           console.log(JSON.stringify(app.globalData.snDisposition));
           // 是否跳转到提示页
@@ -244,23 +233,22 @@ Page({
   handleValue(val) {
     let that = this;
     if (val) {
-      let form = {
+      app.data.brushingCardUserIInfo = {
         name: app.data.userInfo.xm,
         idNum: app.data.userInfo.sfzh,
         photoBase64: app.data.userInfo.avatar,
       }
-      app.data.brushingCardUserIInfo = form
       console.log('1:1比对-联网查询', val);
       that.backToSpecifiedPage('/pages/resultPage/index?result=1:1比对&type=手输1:1')
     } else {
       setTimeout(function () {
         // 捕获到联网查询错误,跳转到重试页面
-        if (app.data.isNetworkQueryError == false) {
+        // if (app.data.isNetworkQueryError == false) {
           let resultText = app.data.clickRetryNum == 0 ? '查询超时,可点击重试' : '查询超时~'
           that.backToSpecifiedPage('/pages/resultPage/index?result=结果页超时&timer=' + app.globalData.snDisposition.resultPageTimeout + '&resultText=' + resultText + '&isShowRetry=' + true)
-        } else {
-          that.handleValue(app.data.userInfo.xm)
-        }
+        // } else {
+        //   that.handleValue(app.data.userInfo.xm)
+        // }
       }, 1000)
     }
   },

+ 2 - 2
pages/settings/advanced/index.axml

@@ -127,7 +127,7 @@
           </view>
         </view>
       </view>
-      <view class=" form-box wid">
+      <!--<view class=" form-box wid">
         <text>启用支付宝扫码登记</text>
         <view
           class="cus-switch"
@@ -168,7 +168,7 @@
             {{item}}
           </view>
         </view>
-      </view>
+      </view>-->
 
 
       <view class="form-box wid" a:if="{{form.transitPushSwitch}}">

+ 3 - 12
pages/settings/advanced/index.js

@@ -255,7 +255,7 @@ Page({
     try {
       // 以下字段根据切换条件重置为默认值
       const fieldArr = [
-        'useIdcard', 'noIdcardRegister', 'wxScanRegister', 'zfbScanRegister'
+        'useIdcard', 'noIdcardRegister', 'wxScanRegister'
       ]
       fieldArr.forEach(field => {
         const fieldValue = form[field]
@@ -287,15 +287,6 @@ Page({
               }
             }
             break
-          // 启用支付宝扫码登记
-          case 'zfbScanRegister':
-            if (!fieldValue) {
-              form = {
-                ...form,
-                zfbQrcodeUrl: '' // 支付宝二维码地址
-              }
-            }
-            break
         }
       })
       let res = await updateConfig(form)
@@ -306,8 +297,8 @@ Page({
       app.globalData.snDisposition.noIdcardInputPhone = form.noIdcardInputPhone;
       app.globalData.snDisposition.wxScanRegister = form.wxScanRegister;
       app.globalData.snDisposition.wxQrcodeUrl = form.wxQrcodeUrl;
-      app.globalData.snDisposition.zfbScanRegister = form.zfbScanRegister;
-      app.globalData.snDisposition.zfbQrcodeUrl = form.zfbQrcodeUrl;
+      // app.globalData.snDisposition.zfbScanRegister = form.zfbScanRegister;
+      // app.globalData.snDisposition.zfbQrcodeUrl = form.zfbQrcodeUrl;
       app.globalData.snDisposition.transitPushUrl = form.transitPushUrl;
       app.globalData.snDisposition.visiteeUrl = form.visiteeUrl;
       // console.log(app.globalData.snDisposition);

+ 48 - 4
utils/api/api.js

@@ -6,10 +6,13 @@ const {
 // let path = 'http://192.168.77.14:9100/yx-fyzd'
 // let path = 'https://test.hz-hanghui.com:18890/yx-fyzd'
 let path = 'https://tx.hz-hanghui.com:8088/yx-fyzd'
-// let platform = 'http://192.168.77.19:8081/hanghui-server-platform'
-let platform = 'https://tx.hz-hanghui.com:8088/hanghui-server-platform'
+// let platform = 'http://192.168.77.15:8081/hanghui-server-platform' // 授权平台配置 测试
+let platform = 'https://tx.hz-hanghui.com:8088/hanghui-server-platform' // 授权平台配置 正式
 let hzHanghui = 'https://noise.hz-hanghui.com:8088/fyzd'
 
+let isDev = false;// 开发版
+let qrUrl = isDev ? 'https://test.hz-hanghui.com:18890' : 'https://tx.hz-hanghui.com:8088'
+
 // 访客机设备-获取配置信息
 const snConfig = data => {
   return request({
@@ -154,7 +157,7 @@ const getVisitDeviceUser = (data) => {
 };
 
 
-// 可配置 公共接口 
+// 可配置 公共接口
 const publicInterface = ({prop, defaultProp, data, method, errorTip}) => {
   const app = getApp()
   const url = app.globalData.snDisposition[prop] ? app.globalData.snDisposition[prop] : path + defaultProp
@@ -167,6 +170,20 @@ const publicInterface = ({prop, defaultProp, data, method, errorTip}) => {
   });
 }
 
+// 特殊码换三要素
+const QRCodeQuery = ({ specialCodeUrl, specialCodeTimeout, specialCodeFailedTips, specialCodeTimeoutTips }, data) => {
+  return request({
+    url: specialCodeUrl,
+    data: data,
+    timeout: specialCodeTimeout ? specialCodeTimeout * 1000 : 5  * 1000,
+    method: "post",
+    type: "application/json",
+    errorTip: '',
+    qrErrorTip: specialCodeFailedTips,
+    timeoutTip: specialCodeTimeoutTips
+  });
+};
+
 // // 访客机-登记信息列表
 // const visitorReportPageList = (data) => {
 //   return request({
@@ -208,6 +225,29 @@ const visitorReport = (data) => {
     errorTip: '获取失败 '
   });
 };
+
+// 获取二维码值
+const getWXScanQRCodeValue = data => {
+  return request({
+    url: qrUrl + "/hanghui-openapi/api/v1/cert/encrypt/config",
+    data: data,
+    method: "post",
+    type: "application/json",
+    errorTip: '获取二维码值请求失败'
+  });
+};
+
+// 根据码值生成二维码
+const createWXScanQRCode = data => {
+  return request({
+    url: qrUrl + "/hanghui-openapi/api/v1/cert/qrcode/create",
+    data: data,
+    method: "post",
+    type: "application/json",
+    errorTip: '根据码值生成二维码请求失败'
+  });
+};
+
 module.exports = {
   snConfig,
   updateConfig,
@@ -229,5 +269,9 @@ module.exports = {
   configList,
 
   //公共配置接口
-  publicInterface
+  publicInterface,
+  QRCodeQuery,
+
+  getWXScanQRCodeValue,
+  createWXScanQRCode
 };

+ 36 - 1
utils/index/index.js

@@ -250,6 +250,40 @@ function debounce(func, delay) {
     }, delay);
   };
 }
+
+/**
+ * @param {Number} len uuid的长度
+ * @param {Boolean} firstU 将返回的首字母置为"u"
+ * @param {Nubmer} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制
+ */
+function guid(len = 32, firstU = true, radix = null) {
+  const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
+  const uuid = []
+  radix = radix || chars.length
+
+  if (len) {
+    // 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
+    for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]
+  } else {
+    let r
+    // rfc4122标准要求返回的uuid中,某些位为固定的字符
+    uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
+    uuid[14] = '4'
+
+    for (let i = 0; i < 36; i++) {
+      if (!uuid[i]) {
+        r = 0 | Math.random() * 16
+        uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]
+      }
+    }
+  }
+  // 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
+  if (firstU) {
+    uuid.shift()
+    return `u${uuid.join('')}`
+  }
+  return uuid.join('')
+}
 module.exports = {
   isCardID: isCardID,
   isPhone: isPhone,
@@ -261,5 +295,6 @@ module.exports = {
   getWaterDrop: getWaterDrop,
   desensitization: desensitization,
   throttle: throttle,
-  debounce: debounce
+  debounce: debounce,
+  guid: guid,
 };