dynamicFaceCheck.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. <template>
  2. <view class="content">
  3. <view class="camera-box" v-if="showcamera">
  4. <view class="camera-bg-box">
  5. <camera
  6. v-if="isOk"
  7. class="camera"
  8. device-position="front"
  9. flash="off"
  10. resolution="low"
  11. ></camera>
  12. </view>
  13. <view v-show="tipsText" class="camera-tip">{{ tipsText }}</view>
  14. </view>
  15. </view>
  16. </template>
  17. <script>
  18. import { mapState, mapMutations } from "vuex";
  19. export default {
  20. data() {
  21. return {
  22. cameraEngine: null,
  23. VKSession: null,
  24. showcamera: true,
  25. tipsText: "开始人脸检测",
  26. isOk: true,
  27. guestId: 0,
  28. idNumber: null,
  29. name: null,
  30. };
  31. },
  32. computed: {
  33. ...mapState("m_business", ["currentHotelId"]),
  34. },
  35. onShow() {
  36. let that = this;
  37. wx.getSetting({
  38. success(res) {
  39. if (!res.authSetting["scope.camera"]) {
  40. //获取摄像头权限
  41. wx.authorize({
  42. scope: "scope.camera",
  43. success() {
  44. that.showcamera = true;
  45. wx.showToast({
  46. title: "授权成功",
  47. icon: "success",
  48. duration: 1000,
  49. });
  50. },
  51. fail() {
  52. console.log("相机授权fail");
  53. wx.showModal({
  54. title: "提示",
  55. content: "尚未进行授权,功能将无法使用",
  56. cancelText: "取消",
  57. confirmText: "授权",
  58. success(res) {
  59. console.log(res);
  60. if (res.confirm) {
  61. console.log("用户点击确定");
  62. wx.openSetting({
  63. //这里的方法是调到一个添加权限的页面,这里可以测试在拒绝授权的情况下设置中是否存在相机选项
  64. success: (res) => {
  65. if (!res.authSetting["scope.camera"]) {
  66. wx.authorize({
  67. scope: "scope.camera",
  68. success() {
  69. wx.showToast({
  70. title: "授权成功",
  71. icon: "success",
  72. duration: 1000,
  73. });
  74. setTimeout(function () {
  75. wx.navigateBack();
  76. }, 1000);
  77. },
  78. fail() {
  79. wx.showToast({
  80. title: "您已取消授权",
  81. icon: "error",
  82. duration: 1000,
  83. });
  84. setTimeout(function () {
  85. wx.navigateBack();
  86. }, 1000);
  87. },
  88. });
  89. }
  90. },
  91. fail: function () {
  92. console.log("相机授权设置失败");
  93. },
  94. });
  95. } else if (res.cancel) {
  96. console.log("用户点击取消");
  97. wx.showToast({
  98. title: "您已取消授权",
  99. icon: "error",
  100. duration: 1000,
  101. });
  102. setTimeout(function () {
  103. wx.navigateBack();
  104. }, 1000);
  105. }
  106. },
  107. });
  108. },
  109. });
  110. }
  111. },
  112. fail(res) {
  113. console.log("22222222222222222" + JSON.stringify(res));
  114. },
  115. });
  116. console.log("OKkkkkkk");
  117. // 初始化相机引擎,更改调用,引用新接口
  118. this.initData();
  119. },
  120. onLoad(options) {
  121. console.log("tipsText", this.tipsText);
  122. this.guestId = options.guestId;
  123. this.idNumber = options.idNumber;
  124. this.name = options.name;
  125. console.log("guestId ", this.guestId);
  126. console.log("idNumber ", this.idNumber);
  127. console.log("name", this.name);
  128. },
  129. methods: {
  130. //visionkit人脸必须函数
  131. async detectFace(frame) {
  132. console.log("frame", frame.data);
  133. this.VKSession.detectFace({
  134. frameBuffer: frame.data,
  135. width: frame.width,
  136. height: frame.height,
  137. scoreThreshold: 0.8,
  138. sourceType: 0,
  139. modelMode: 1,
  140. });
  141. },
  142. //初始化相机引擎
  143. initData() {
  144. let that = this;
  145. //使用visionkit
  146. that.cameraEngine = wx.createCameraContext();
  147. let count = 0;
  148. //初始化相机
  149. const listener = that.cameraEngine.onCameraFrame((frame) => {
  150. count++;
  151. //每十帧分析一次
  152. if (count === 10) {
  153. this.detectFace(frame);
  154. count = 0;
  155. }
  156. });
  157. //开始监听数据帧
  158. listener.start();
  159. //创建VK对象
  160. that.VKSession = wx.createVKSession({
  161. version: "v1",
  162. track: {
  163. plane: {
  164. mode: 1,
  165. },
  166. face: {
  167. mode: 2,
  168. },
  169. },
  170. });
  171. //启动VK对象
  172. that.VKSession.start((errno) => {
  173. console.log("VKSession.start errno", errno);
  174. if (errno) {
  175. wx.showModal({
  176. title: "提示",
  177. content: "网络错误,请退出后重试",
  178. showCancel: false,
  179. confirmText: "确定",
  180. success(res) {
  181. console.log(res);
  182. if (res.confirm) {
  183. wx.navigateBack();
  184. }
  185. },
  186. });
  187. }
  188. });
  189. that.VKSession.on("updateAnchors", (anchors) => {
  190. console.log("anchors", anchors);
  191. console.log("anchors.length", anchors.length);
  192. anchors.forEach((anchor) => {
  193. console.log("anchor.points", anchor.points);
  194. console.log("anchor.origin", anchor.origin);
  195. console.log("anchor.size", anchor.size);
  196. console.log("anchor.angle", anchor.angle);
  197. console.log("anchor", anchor.confidence);
  198. if (anchors.length > 1) {
  199. that.tipsText = "请保证只有一个人";
  200. } else {
  201. const { pitch, roll, yaw } = anchor.angle;
  202. const standard = 0.3;
  203. if (
  204. Math.abs(pitch) >= standard ||
  205. Math.abs(roll) >= standard ||
  206. Math.abs(yaw) >= standard
  207. ) {
  208. that.tipsText = "请平视摄像头";
  209. } else if (
  210. anchor.origin.x < 0.15 ||
  211. anchor.origin.x > 0.3 ||
  212. anchor.origin.y < 0.2 ||
  213. anchor.origin.y > 0.45
  214. ) {
  215. this.tipsText = "请将人脸对准中心位置";
  216. } else if (
  217. anchor.confidence[0] <= 0.8 ||
  218. anchor.confidence[1] <= 0.8 ||
  219. anchor.confidence[2] <= 0.8 ||
  220. anchor.confidence[3] <= 0.8 ||
  221. anchor.confidence[4] <= 0.8
  222. ) {
  223. that.tipsText = "请勿遮挡五官";
  224. } else {
  225. listener.stop();
  226. that.tipsText = "即将拍照,请保持!";
  227. setTimeout(function () {
  228. that.handleTakePhotoClick();
  229. }, 1000);
  230. return;
  231. }
  232. }
  233. });
  234. });
  235. },
  236. // 拍照
  237. handleTakePhotoClick() {
  238. this.tipsText = "正在上传...";
  239. uni.showLoading({
  240. title: "正在人脸认证,请稍后",
  241. });
  242. this.cameraEngine.takePhoto({
  243. quality: "normal",
  244. success: ({ tempImagePath }) => {
  245. let mybase64 = wx
  246. .getFileSystemManager()
  247. .readFileSync(tempImagePath, "base64");
  248. this.afterRead(mybase64);
  249. },
  250. });
  251. },
  252. //上传
  253. async afterRead(mybase64) {
  254. let that = this;
  255. uni.$http
  256. .post("/faceVerification/checkPic", {
  257. hotelId: this.currentHotelId,
  258. faceData: mybase64,
  259. })
  260. .then(async (res) => {
  261. uni.hideLoading();
  262. console.log("mybase64", mybase64);
  263. if (res.data.code === 200 && res.data.success === true) {
  264. that.isOk = false;
  265. uni.showLoading({
  266. title: "正在人证比对,请稍后",
  267. });
  268. let yunjiFaceCheckInfo = {
  269. idNo: that.idNumber,
  270. name: that.name,
  271. image: mybase64,
  272. };
  273. let res = await uni.$http.post(
  274. "/faceVerification/yunjiVerification",
  275. yunjiFaceCheckInfo
  276. );
  277. if (res.data.success === true) {
  278. uni.showModal({
  279. content: "人证比对通过!",
  280. showCancel: false,
  281. success: function (res) {
  282. if (res.confirm) {
  283. console.log("用户点击确定");
  284. setTimeout(function () {
  285. let pages = getCurrentPages();
  286. console.log("pages", pages);
  287. let prevPage = pages[pages.length - 2];
  288. // prevPage.setData({
  289. // pic: mybase64,
  290. // });
  291. wx.navigateBack({
  292. success: () => {
  293. prevPage.$vm.setGuestPicBase64ById(
  294. that.guestId,
  295. mybase64
  296. );
  297. },
  298. });
  299. }, 1000);
  300. }
  301. },
  302. });
  303. } else {
  304. uni.showModal({
  305. content: "人证比对失败,请重试",
  306. showCancel: false,
  307. success: function (res) {
  308. if (res.confirm) {
  309. console.log("用户点击确定");
  310. that.initData();
  311. }
  312. },
  313. });
  314. }
  315. } else {
  316. uni.showModal({
  317. content: "人脸认证失败,请重试",
  318. showCancel: false,
  319. success: function (res) {
  320. if (res.confirm) {
  321. console.log("用户点击确定");
  322. that.initData();
  323. }
  324. },
  325. });
  326. }
  327. console.log("checkPicRes", res);
  328. });
  329. },
  330. },
  331. };
  332. </script>
  333. <style lang="scss">
  334. .content {
  335. position: absolute;
  336. top: 0;
  337. right: 0;
  338. bottom: 0;
  339. left: 0;
  340. .camera-box {
  341. position: relative;
  342. width: 100%;
  343. height: 100%;
  344. }
  345. .camera-bg-box {
  346. position: relative;
  347. width: 100%;
  348. height: 100%;
  349. overflow: hidden;
  350. &::after {
  351. content: "";
  352. position: absolute;
  353. left: 50%;
  354. top: 50%;
  355. transform: translateX(-50%) translateY(-50%);
  356. border-radius: 100%;
  357. width: 600rpx;
  358. height: 600rpx;
  359. border: 1000rpx solid rgba(255, 255, 255, 0.998);
  360. }
  361. }
  362. .camera {
  363. width: 100%;
  364. height: 100%;
  365. border-top: 200rpx solid black;
  366. border-bottom: 200rpx solid black;
  367. box-sizing: border-box;
  368. }
  369. .camera-tip {
  370. position: absolute;
  371. bottom: 220rpx;
  372. left: 50%;
  373. color: rgb(0, 0, 0);
  374. transform: translateX(-50%);
  375. // .text-40-fff-600();
  376. }
  377. }
  378. </style>