getPortrait.vue 9.6 KB
<template>
	<view class="big-box" :style="{'padding-top': statusBarHeight + 'px'}" v-if="statusBarHeight">
		<view class="nav-bar" :style="{'height': navHeight + 'px'}"></view>
		<text class="title">扫脸获取您的照片</text>
		<view class="scan">
			<camera class="circle" device-position="front" flash="off" @error="error"></camera>
			<view class="surface" v-if="show">
				<view class="camera-tip">请正对镜头</view>
				<text>{{text}}</text>
			</view>
			<image class="photo" v-show="src" :src="src"></image>
		</view>
		<view class="icon-box">
			<view class="item">
				<image src="./static/album/will-lit.png"></image>
				<text>保持光线充足</text>
			</view>
			<view class="item">
				<image src="./static/album/face-screen.png"></image>
				<text>请面对屏幕</text>
			</view>
			<view class="item">
				<image src="./static/album/no-shelter.png"></image>
				<text>不得遮挡面部</text>
			</view>
		</view>
		<text class="tip">获取照片需先在拍摄点摄影</text>
		<u-overlay :show="maskShow" @click="closeClick">
			<view class="mask" @tap.stop>
				<text class="countdown" :class="{'hidden': maskCount <= 0}">{{maskCount}}s</text>
				<view class="tip">
					<view>未找到您的照片</view>
					<view class="small">请在拍摄点拍摄后重试</view>
				</view>
				<u-button type="info" size="mini" shape="circle" @click="returnClick">返回</u-button>
			</view>
		</u-overlay>
	</view>
</template>

<script>
export default {
  data() {
    return {
      statusBarHeight: 0,
      capsule: 0,
      navHeight: 0,
      src: '', //照片
      text: 3, //倒计时
      show: false, //摄像头倒计时文本
      base64: '', //照片base64
      maskShow: false,//弹窗显示
      maskCount: 3,//弹窗倒计时
      queryData: {},//查询参数
      defaultBrightness: 0.5,//屏幕亮度
      options: {},//路由传参
      loop: null//弹窗关闭倒计时
    }
  },
  methods: {
    returnClick() {
      if(this.maskCount > 0) return
      this.maskShow = false
      uni.navigateBack({
			  delta: 1
      })
    },
    closeClick() {
      if(this.maskCount > 0) return
      this.maskShow = false
      this.takePhoto()
    },
    recordDeviceInfo() {//---记录设备信息
      this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight // 状态栏高度
      this.capsule = uni.getMenuButtonBoundingClientRect() // 胶囊大小、位置数据
      this.navHeight = (this.capsule.top - this.statusBarHeight) * 2 + this.capsule.height // 导航栏高度
    },
    openCamera() { //---用户首次进入打开权限
      uni.authorize({ //摄像头
        scope: 'scope.camera',
        success: (res) => {
          console.log('已打开摄像头权限')
          this.getQueryField()
        },
        fail: (res) => {
          uni.showModal({
            content: '检测到您没打开摄像头权限,是否去设置打开?',
            confirmText: '确认',
            cancelText: '取消',
            success: (res) => {
              if (res.confirm) {
                uni.openSetting({
                  success: (res) => {
                    console.log(res)
                    this.getQueryField()
                  },
                  fail: (err) => {
                    console.log(err)
                  }
                })
              } else {
                uni.navigateBack({
                  delta: 1
                })
              }
            }
          })
        }
      })
      uni.authorize({
        scope: 'scope.writePhotosAlbum',
        success: (res) => {
          console.log('已打开保存到相册权限')
        },
        fail: (res) => {
          uni.showModal({
            content: '检测到您没打开相册权限,是否去设置打开?',
            confirmText: '确认',
            cancelText: '取消',
            success: (res) => {
              if (res.confirm) {
                uni.openSetting({
                  success: (res) => {
                    console.log('已打开保存到相册权限')
                  },
                  fail: (err) => {
                    console.log('保存到相册权限打开失败' + err)
                  }
                })
              } else {
                uni.navigateBack({
                  delta: 1
                })
              }
            }
          })
        }
      })
    },
    getQueryField() {//---获取查询参数
      const merchantId = this.options.merchantId
			
      this.$request('scenic/albumConfig/getAlbumConfig',{merchantId}).then(res => {//创建任务
			  if (res.code === '00') {
          this.queryData = res.data
          this.takePhoto()
			  }else{
					this.handleNotFound()
			    uni.showToast({
			      title: '查询参数获取失败',
			      icon: 'none'
			    })
			  }
      })
    },
    query() { //人脸查询
      uni.showLoading({
        title: '人脸识别中'
      })
      let data = {
        openid: uni.getStorageSync('openid'), //openid
        uri: this.base64, //人脸图片base64编码
        ...this.queryData
      }
      this.$request('wechatUser/aliFace/faceSearch',data).then(res => {//创建任务
        uni.hideLoading()
        if (res.code === '00') {
          if(res.data.faceIds && res.data.faceIds.length) {
            uni.setScreenBrightness({
              value: this.defaultBrightness, //屏幕亮度值,范围 0~1,0 最暗,1 最亮
            })
            uni.navigateTo({
              url: `./myPhotoAlbum/myPhotoAlbum?faceIds=${JSON.stringify(res.data.faceIds)}`
            })
          }else {
            this.handleNotFound()
          }
        }else{
          this.handleNotFound()
        }
      })
    },
    handleNotFound() {//---处理没有找到照片或返回错误的逻辑
      this.maskShow = true
      this.maskCount = 3
      var loop = setInterval(() => {
			  this.maskCount -= 1
			  if(this.maskCount <= 0) {
			    this.src = ''
			    clearInterval(loop)
			    uni.setScreenBrightness({
					  value: this.defaultBrightness, //屏幕亮度值,范围 0~1,0 最暗,1 最亮
			    })
			  }
      },1000)
    },
    takePhoto() { //扫脸
      this.src = ''
      this.text = 3
      this.show = true
      var test = setInterval(() => {
        this.text = this.text - 1
        if (this.text === 0) {
          clearInterval(test)
          this.show = false
          const ctx = uni.createCameraContext()
          ctx.takePhoto({
            quality: 'high',
            success: (res) => {
              this.src = res.tempImagePath
              uni.getFileSystemManager().readFile({ //图片转base64
                filePath: res.tempImagePath, //选择图片返回的相对路径
                encoding: 'base64', //编码格式
                success: res => { //成功的回调
                  this.base64 = res.data
                  this.query()
                }
              })
            }
          })
        }
      }, 1000)
    },
    error(e) { //相机报错
		  uni.showModal({
        title: '提示',
        content: e.detail,
		    showCancel: false
		  })
    },
  },
  onLoad(options) {
    this.options = options
    this.recordDeviceInfo()
    uni.getScreenBrightness({//获取屏幕亮度
      success(res) {
        this.defaultBrightness = res.value
      },
      fail() {
        this.defaultBrightness = 0.5//如果获取失败设置亮度为中间值
      }
    })
    uni.setScreenBrightness({
      value: 0.8, //屏幕亮度值,范围 0~1,0 最暗,1 最亮
    })
    this.openCamera()
  }
}
</script>

<style lang="scss" scope>
	.big-box {
		display: flex;
		flex-direction: column;
		align-items: center;
		height: 100%;
		background-color: #fff;
		.title {
			font-size: 32rpx;
			margin: 30rpx 0 62rpx 0;
		}
		.scan {
			position: relative;
			width: 468rpx;
			height: 468rpx;
			margin-bottom: 20%;
			z-index: 1;
			.circle,
			.surface,
			.photo {
				position: absolute;
				left: 0;
				top: 0;
				width: 100%;
				height: 100%;
				border-radius: 50%;
				overflow: hidden;
			}
			.circle {
				border: 1px dashed #999;
				box-sizing: border-box;
				background-color: #fff;
				-webkit-transform: rotate(0deg);
			}
			.surface {
				display: flex;
				flex-direction: column;
				justify-content: center;
				align-items: center;
				color: #fff;
				font-size: 48rpx;
				z-index: 200;
				.camera-tip {
					margin-bottom: 48rpx;
				}
			}
			.photo {
				z-index: 200;
			}
			&::before,
			&::after {
				position: absolute;
				left: -12rpx;
				top: 0;
				content: '';
				width: 100%;
				height: 100%;
				border-radius: 50%;
				background-color: #ECF5FF;
				z-index: -1;
			}
			&::after {
				left: 12rpx;
				background-color: #CEE5FF;
			}
		}
		.icon-box {
			display: flex;
			justify-content: space-evenly;
			align-self: stretch;
			margin-bottom: 20%;
			.item {
				display: flex;
				flex-direction: column;
				align-items: center;
				text {
					font-size: 24rpx;
					font-weight: 700;
					color: #191919;
				}
			}
			image {
				width: 88rpx;
				height: 88rpx;
				margin-bottom: 20rpx;
			}
		}
		.tip {
			font-size: 32rpx;
			font-weight: 700;
			color: #3688FF;
		}
		/deep/.u-transition {
			display: flex;
			justify-content: center;
			align-items: center;
		}
	}
	
	.mask {
		display: flex;
		justify-content: space-between;
		flex-direction: column;
		align-items: center;
		width: 576rpx;
		height: 338rpx;
		padding: 16rpx;
		border-radius: 16rpx;
		background-color: #fff;
		.countdown {
			align-self: flex-end;
		}
		.countdown.hidden {
			visibility: hidden;
		}
		.tip {
			font-size: 36rpx;
			color: #3688FF;
			margin: 32rpx 0 24rpx 0;
			text-align: center;
			.small {
				font-size: 28rpx;
				color: #333;
			}
		}
	}
</style>