liyongli před 2 roky
rodič
revize
5d86c524c1

+ 1 - 0
miniprogram/api/index.ts

@@ -53,6 +53,7 @@ function getUser(params:WechatMiniprogram.requestParamsData) {
   return request({
     url: "/v3/user-state",
     data: params.data,
+    noloading: params.noloading,
     header:{
       Authorization: wx.getStorageSync("token"),
       ...params.header

+ 4 - 0
miniprogram/pages/downloadPage/index.ts

@@ -30,6 +30,7 @@ Page({
             icon: "none",
             duration: 2000
           })
+          console.log('btn')
           res.PAY ? this.downloadVideo() : this.toPAY();
         },
       })
@@ -40,6 +41,7 @@ Page({
       title: ""
     })
     app.getUser({
+      noloading: true,
       data: {},
       success: (rule: any) => {
         if (!rule.PAY) return
@@ -53,6 +55,7 @@ Page({
                   this.setData({
                     videoSrc: r.url
                   })
+                  // 保存到相册
                   wx.saveVideoToPhotosAlbum({
                     filePath: res.tempFilePath,
                     success: () => {
@@ -171,6 +174,7 @@ Page({
    */
   onShow() {
     // 如果支付成功则下载视频
+    console.log('show')
     if (apiPay) this.downloadVideo();
   },
 

+ 2 - 2
miniprogram/pages/entry/index.ts

@@ -41,8 +41,8 @@ Page({
       success: () => {
         // 进入人脸识别
         let url = "/pages/faceRecognition/index";
-        const version:string = app.globalData.SystemInfo?.SDKVersion || "";
-        if(compareVersion(version, "2.20.0")) url = "/pages/faceRecognitionVK/index"
+        const version: string = app.globalData.SystemInfo?.SDKVersion || "";
+        if (compareVersion(version, "2.25.0") !== -1) url = "/pages/faceRecognitionVK/index"
         wx.navigateTo({ url })
       }
     })

+ 2 - 0
miniprogram/pages/faceRecognitionVK/index.json

@@ -1,4 +1,6 @@
 {
+  "navigationBarBackgroundColor": "#2AB0FF",
+  "navigationBarTextStyle": "white",
   "usingComponents": {
   }
 }

+ 65 - 15
miniprogram/pages/faceRecognitionVK/index.scss

@@ -1,23 +1,73 @@
-/* pages/faceRecognition/index.wxss */
-@import "../../components/camera-face/index.wxss";
-
-page {
+/* components/camera-face/index.scss */
+.page-body {
+  width: 100%;
+  height: 100%;
   background: #ffffff;
-  height: 100vh;
+  overflow: auto
+}
+
+.head {
+  padding-top: 154rpx;
+  padding-bottom: 262rpx;
+  background-image: url(https://cxzx.smcic.net/topic/tool/img/miniprogram/faceBg.jpg);
+  background-size: 100% 100%;
+  height: 72.9%;
+  box-sizing: border-box;
+}
+
+.camera {
+  width: 452rpx;
+  height: 452rpx;
+  z-index: 1;
+  border-radius: 50%;
+  margin: 0 auto 0 auto;
+}
+
+.half-circle {
+  width: 480rpx;
+  height: 100rpx;
+  background-color: rgba(0, 0, 0, 0.2);
+  border-radius: 50% 50% 0 0;
   display: flex;
+  justify-content: center;
   align-items: center;
+  color: #ffffff;
+  font-family: "Microsoft YaHei";
+  font-size: 30rpx;
+  color: white;
+  line-height: 70rpx;
 }
 
-.page {
-  width: 100%;
-  height: 750rpx;
+/* 底部按钮和提示文字 */
+.bottom-tips {
+  text-align: center;
+  height: 188rpx;
+  font-size: 32rpx;
+  font-family: PingFangSC-Regular, PingFang SC;
+  font-weight: 400;
+  color: #333333;
+  line-height: 188rpx;
+}
 
-  .camera{
-    width: 80%;
-    height: 80%;
-    margin: 0 auto 2em auto;
-    border-radius: 50%;
-    background-color: #000000;
-  }
+.faceBtn {
+  color: #ffffff;
+  margin: 81rpx auto 0 auto;
+  width: 500rpx;
+  text-align: center;
+  height: 92rpx;
+  line-height: 92rpx;
+  border-radius: 56rpx;
+  background: linear-gradient(180deg, #26B4EC 0%, #2F8AFF 100%);
 }
 
+/* 顶部提示文字 */
+.top-tips {
+  height: 50rpx;
+  font-size: 36rpx;
+  font-family: PingFangSC-Medium, PingFang SC;
+  font-weight: 500;
+  color: #FFFFFF;
+  line-height: 50rpx;
+  text-align: center;
+  margin-bottom: 138rpx;
+}

+ 176 - 96
miniprogram/pages/faceRecognitionVK/index.ts

@@ -1,9 +1,23 @@
 // pages/faceRecognition/index.ts
 import { base } from "../../config/index";
-import { compareVersion } from "../../utils/util";
 let ctx: WechatMiniprogram.CameraContext | undefined = undefined;
+let listener: WechatMiniprogram.CameraFrameListener | undefined;
 let createVKSession: WechatMiniprogram.VKSession | undefined = undefined;
+let innerAudioContext: WechatMiniprogram.InnerAudioContext;
 const app = getApp<IAppOption>();
+const topTips = {
+  ready: '请正对手机,保持光线充足',
+  front: '请正对屏幕',
+  left: '请向左转头',
+  right: '请向右转头',
+}
+const bottomTips = {
+  recording: '脸部信息录入中...',
+  complete: '脸部信息录入成功',
+  error: '脸部信息录入失败'
+}
+let T: number = 0;
+const daoJiShi: number = 15;
 Page({
 
   /**
@@ -13,128 +27,154 @@ Page({
     isStartVideo: false, // 是否点击开始按钮
     isEmpower: false, // 是否授权
     isUpLoad: false, // 是否上传中
+    initFace: false, // 是否初始化人脸识别
     isTranscribe: false, // 是否录制中
-
+    seconds: 0, // 倒计
+    topTips: topTips.ready, // 提示语句
+    bottomTips: "", // 底部提示语句
     buttomText: "录制"
   },
 
   // 开始初始化录制
-  initCamera() {
+  async initCamera() {
     if (this.data.isStartVideo) return;
+    wx.showLoading({
+      title: ""
+    })
     this.setData({
       isStartVideo: true
     })
     wx.nextTick(() => {
-      this.createVK();
-      wx.showLoading({
-        title: ""
-      })
-      ctx = wx.createCameraContext();
-      ctx.startRecord({
-        timeout: 15, // 录制时长
-        timeoutCallback: () => {
-          // 超出录制时长 关闭录屏
-          this.overVideo();
-        },
-        success: () => {
-          // 调用成功,开始录制
-          wx.hideLoading();
-        },
-        fail: () => {
-          // 调用失败
-          wx.hideLoading();
-          wx.showToast({
-            icon: "none",
-            title: "相机调用失败",
-            duration: 2000
-          })
-        },
-        complete: () => { }
-      })
+      this.getMssage().then(async (r: any) => {
+        console.log('是否授权发送消息:', r)
+        if (!ctx) ctx = wx.createCameraContext();
+        this.createVK();
+        ctx.startRecord({
+          timeout: daoJiShi, // 录制时长
+          selfieMirror: false,
+          timeoutCallback: (res) => {
+            // 超出录制时长 关闭录屏
+            this.setData({
+              isStartVideo: false,
+              bottomTips: "",
+              topTips: topTips.ready, // 提示语句
+            })
+            createVKSession?.stop();
+            listener?.stop();
+            this.getUrl(res);
+          },
+          success: () => {
+            // 调用成功,开始录制
+            wx.hideLoading();
+            this.setData({
+              seconds: daoJiShi,
+              bottomTips: bottomTips.recording,
+              topTips: topTips.front
+            });
+            innerAudioContext.src = "assets/voice/front.mp3";
+            innerAudioContext.play();
+          },
+          fail: () => {
+            // 调用失败
+            wx.hideLoading();
+            wx.showToast({
+              icon: "none",
+              title: "相机调用失败",
+              duration: 2000
+            })
+          },
+          complete: () => { }
+        })
+      });
     })
   },
+  // 添加监听
+  addListen() {
+    createVKSession?.start(() => { });
+    T = Date.now();
+    !listener && (listener = ctx?.onCameraFrame((frame: any) => {
+      const Time = daoJiShi * 1000 - (Date.now() - T);
+      if (Time % 1000 >= 50) return
+      const s = Math.floor(Time / 1000);
+      if (s == 10) {
+        innerAudioContext.src = "assets/voice/left.mp3";
+        this.setData({
+          topTips: topTips.left
+        })
+      }
+      if (s == 5) {
+        innerAudioContext.src = "assets/voice/right.mp3";
+        this.setData({
+          topTips: topTips.right
+        })
+      }
+      if (s % 5 === 0 && s !== 0) innerAudioContext.play();
+      this.setData({
+        seconds: s
+      })
 
+      // 识别人脸是否在画面种
+      createVKSession?.detectFace({
+        frameBuffer: frame.data, // 图片 ArrayBuffer 数据。人脸图像像素点数据,每四项表示一个像素点的 RGBA
+        width: frame.width, // 图像宽度
+        height: frame.height, // 图像高度
+        scoreThreshold: 0.5, // 评分阈值
+        sourceType: 1
+      })
+    }));
+    listener?.start();
+  },
   // 创建人脸追踪
   createVK() {
-    console.log("开始追踪人脸");
-    createVKSession = wx.createVKSession({
+    // 初始化人脸识别
+    if (this.data.initFace) return this.addListen();
+    if (!createVKSession) createVKSession = wx.createVKSession({
       version: "v1",
       track: {
         plane: {
-          mode: 3
-        },
-        face: {
           mode: 1
-        }
+        },
+        face: { mode: 2 } // mode: 1 - 使用摄像头;2 - 手动传入图像
       },
     })
-
-    createVKSession.on("updateAnchors", anchors => {
-      console.log("检测到人脸", anchors)
-      if (!this.data.isTranscribe) {
-        this.setData({
-          isTranscribe: true
-        })
-      }
-    })
-
-    // 当人脸从相机中离开时,会触发 removeAnchors 事件
-    createVKSession.on('removeAnchors', () => {
+    // 静态图片检测模式下,每调一次 detectFace 接口就会触发一次 updateAnchors 事件
+    createVKSession?.on('removeAnchors', () => {
       wx.showToast({
-        icon: "none",
-        title: "未检测到人脸,请重新录制",
-        duration: 2000
-      })
-      //  录制失败
+        title: "未检测到人脸, 请重新采集",
+        icon: "error"
+      });
       this.overVideo();
     })
-
-    createVKSession.start((errno) => {
-      console.log(errno);
-    })
+    this.addListen();
   },
-
   // 结束录像
   overVideo() {
     if (!ctx || !this.data.isStartVideo) return;
-    wx.showLoading({
-      title: ""
-    })
-    createVKSession?.stop();
     ctx.stopRecord({
       compressed: true,
-      success: res => {
-        // 成功结束
-        wx.hideLoading();
-        this.getUrl(res);
-      },
-      fail: () => {
-        // 结束失败
-        wx.hideLoading();
-        wx.showToast({
-          icon: "none",
-          title: "相机关闭失败",
-          duration: 2000
-        })
-      },
       complete: () => {
+        createVKSession?.stop();
+        innerAudioContext?.pause();
+        listener?.stop();
         this.setData({
-          isStartVideo: false
+          isStartVideo: false,
+          bottomTips: "",
+          topTips: topTips.ready,
+          seconds: 0
         })
       }
     })
   },
-
   // 获取本地临时地址
   getUrl(res: WechatMiniprogram.StartRecordTimeoutCallbackResult) {
     this.setData({
       isUpLoad: true
     })
     wx.showLoading({
-      title: ""
+      title: '上传进度:0%',
+      mask: true //是否显示透明蒙层,防止触摸穿透
     })
-    wx.uploadFile({
-      // 仅为示例,非真实的接口地址,视频上传
+    const uploadTask = wx.uploadFile({
       url: base.url + '/v3/upload',
       filePath: res.tempVideoPath,
       name: 'file', //服务器定义的Key值
@@ -142,23 +182,35 @@ Page({
       header: {
         Authorization: wx.getStorageSync("token")
       },
-      success: function (res) {
-        console.log(res)
+      success: () => {
         wx.hideLoading();
         wx.showToast({
           title: "上传成功",
           duration: 2000,
           icon: "none"
+        });
+        this.setData({
+          topTips: topTips.ready, // 提示语句
+          bottomTips: bottomTips.complete
         })
+        let time = setTimeout(() => {
+          clearTimeout(time);
+          wx.reLaunch({
+            url: "/pages/downloadPage/index"
+          })
+        }, 2000)
       },
-      fail: function (res) {
-        console.log(res)
+      fail: () => {
         wx.hideLoading();
         wx.showToast({
           title: "上传失败",
           icon: "none",
           duration: 2000
         })
+        this.setData({
+          topTips: topTips.ready, // 提示语句
+          bottomTips: bottomTips.error
+        })
       },
       complete: () => {
         this.setData({
@@ -166,24 +218,51 @@ Page({
         })
       }
     })
+    //监听上传进度变化事件
+    uploadTask.onProgressUpdate((res) => {
+      wx.showLoading({
+        title: '上传进度:' + res.progress + '%',
+        mask: true //是否显示透明蒙层,防止触摸穿透
+      })
+    })
   },
-
   // 非正常中止
-  improperStop() { },
-
+  improperStop() {
+    wx.navigateBack();
+  },
   // 未授权
-  unauthorized() { },
-
+  unauthorized() {
+    wx.showToast({
+      title: "拒绝授权将无法录制视频信息"
+    });
+    wx.navigateBack();
+  },
   // 初始化完成
   initialization() { },
-
+  // 获取消息授权
+  getMssage() {
+    return new Promise((resolve) => {
+      if (!app.globalData.configPage?.messageID || !wx.canIUse("requestSubscribeMessage")) {
+        resolve("reject");
+        return
+      }
+      wx.requestSubscribeMessage({
+        tmplIds: app.globalData.configPage?.messageID || [],
+        success: (res: WechatMiniprogram.RequestSubscribeMessageSuccessCallbackResult) => {
+          resolve(res.p1mpCydIQ6OtxCSa62NaSFiEkQiTsb8KPFaAs1SuKMw || 'reject');
+        },
+        fail: () => {
+          resolve("reject");
+        }
+      })
+    })
+  },
   /**
    * 生命周期函数--监听页面加载
    */
-  onLoad(opt) {
-    console.log(opt)
-    const SDKVersion: string = app.globalData.SystemInfo?.SDKVersion || "";
-    compareVersion(SDKVersion, '1.9.6');
+  onLoad() {
+    innerAudioContext = wx.createInnerAudioContext();
+    innerAudioContext.loop = false;
   },
 
   /**
@@ -204,6 +283,7 @@ Page({
    */
   onHide() {
     // 在录制中退出后台页面隐藏,返回上一页,确保重新进入当前页
+    this.overVideo();
   },
 
   /**
@@ -230,9 +310,9 @@ Page({
   /**
    * 用户点击右上角分享
    */
-  onShareAppMessage() {
+  // onShareAppMessage() {
 
-  },
+  // },
 })
 
 export { }

+ 1 - 1
miniprogram/pages/home/index.ts

@@ -26,7 +26,7 @@ Page({
           // 未上传人脸信息,跳转人脸采集页
           let url = "/pages/faceRecognition/index";
           const version: string = app.globalData.SystemInfo?.SDKVersion || "";
-          if (compareVersion(version, "2.20.0")) url = "/pages/faceRecognitionVK/index"
+          if (compareVersion(version, "2.25.0") !== -1) url = "/pages/faceRecognitionVK/index";
           wx.navigateTo({ url })
           return;
         }

+ 3 - 3
miniprogram/utils/request.ts

@@ -2,7 +2,7 @@ import { base } from "../config/index"
 import { errHttp } from "./util";
 
 export default function request(params: WechatMiniprogram.requestParamsData) {
-  wx.showLoading({
+  !params.noloading && wx.showLoading({
     title: ""
   })
   const url = params.baseUrlNone ? params.url : base.url + params.url
@@ -12,7 +12,7 @@ export default function request(params: WechatMiniprogram.requestParamsData) {
     header: params.header,
     dataType: params.dataType || 'json',
     success: (res: any) => {
-      wx.hideLoading();
+      !params.noloading && wx.hideLoading();
       if (res.statusCode !== 200 || res.data.code !== 0) {
         // code 401  token过期
         errHttp(res.data.message || res.data.message);
@@ -22,7 +22,7 @@ export default function request(params: WechatMiniprogram.requestParamsData) {
     },
     method: params.method || "GET",
     fail: err => {
-      wx.hideLoading();
+      !params.noloading && wx.hideLoading();
       wx.showToast({
         title: err.errMsg || "请稍后再试",
         icon: "none",

+ 1 - 8
project.private.config.json

@@ -45,14 +45,7 @@
         },
         {
           "name": "",
-          "pathName": "pages/faceRecognitionVk/index",
-          "query": "",
-          "launchMode": "default",
-          "scene": null
-        },
-        {
-          "name": "",
-          "pathName": "pages/faceRecognitionVk/index",
+          "pathName": "pages/faceRecognitionVK/index",
           "query": "",
           "launchMode": "default",
           "scene": null

+ 1 - 0
typings/types/wx/lib.local.tool.d.ts

@@ -8,6 +8,7 @@ declare namespace WechatMiniprogram {
     dataType?: 'json' | '其他';
     success:AccessCompleteCallback;
     baseUrlNone?: boolean;
+    noloading?: boolean;
     complete?: (com? :any) => void;
   }
 }