You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
427 lines
9.6 KiB
427 lines
9.6 KiB
<template>
|
|
<view class="yd-check" :style="{'width': winWidth+'px', 'height': winHeight+'px'}">
|
|
<view class="check-preview">
|
|
<view class="check-preview__content">
|
|
<camera_preview ref="aliveDetect" class="check-preview__camera"></camera_preview>
|
|
<image class="check-preview__mask" :style="{ backgroundColor: maskColor }"
|
|
src="/static/shibie/alive_mask@3x.png" @load="handleImgLoad"></image>
|
|
</view>
|
|
<view class="check-preview__audio" @click="toggleAudioSwitch">
|
|
<image class="check-preview__switch"
|
|
:src="enableAudio ? '/static/shibie/audio_open@3x.png' : '/static/shibie/audio_close@3x.png'"></image>
|
|
</view>
|
|
<view class="check-preview__timer progress-timer">
|
|
<text class="txt">{{ restSec }}</text>
|
|
<view class="progress-timer__right">
|
|
<view ref="rightCircle" class="progress-timer__circle progress-timer__circle--right"></view>
|
|
</view>
|
|
<view class="progress-timer__left">
|
|
<view ref="leftCircle" class="progress-timer__circle progress-timer__circle--left"></view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="check-process">
|
|
<view class="check-process__tip">{{ curAction.tip }}</view>
|
|
<image class="check-process__img" :src="`/static/shibie/${curAction.image}`"></image>
|
|
<view class="check-steps">
|
|
<view v-for="(item,index) in commands" :key="index"
|
|
:class="['check-steps__item', curAction.step === index ? 'check-steps__item--active' : '']">
|
|
<text v-if="curAction.step === index" class="check-steps__text">{{ index+1 }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import api from '@/api/index.js'
|
|
const DETECT_ACTION_TYPES = {
|
|
'1': ['向右转头', 'turn_right.gif', 'turn_right.wav'],
|
|
'2': ['向左转头', 'turn_left.gif', 'turn_left.wav'],
|
|
'3': ['张嘴动作', 'open_mouth.gif', 'open_mouth.wav'],
|
|
'4': ['眨眼动作', 'open_eyes.gif', 'open_eyes.wav']
|
|
}
|
|
const innerAudioContext = uni.createInnerAudioContext()
|
|
innerAudioContext.onPlay(() => {
|
|
console.log('音频开始播放')
|
|
})
|
|
innerAudioContext.onError((res) => {
|
|
console.log(res.errMsg)
|
|
console.log(res.errCode)
|
|
})
|
|
const animation = weex.requireModule('animation')
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
curAction: {
|
|
step: 0,
|
|
tip: '',
|
|
image: 'pic_front.png'
|
|
},
|
|
restSec: 0,
|
|
enableAudio: true,
|
|
timer: null,
|
|
maskColor: '#fff',
|
|
isTimeout: false,
|
|
commands: [],
|
|
winWidth: 0,
|
|
winHeight: 0,
|
|
idCard: "",
|
|
realName: ""
|
|
};
|
|
},
|
|
onLoad(o) {
|
|
this.realName = decodeURIComponent(o.realName);
|
|
this.idCard = o.idCard;
|
|
console.log(o)
|
|
this.winWidth = uni.getSystemInfoSync().windowWidth;
|
|
this.winHeight = uni.getSystemInfoSync().windowHeight;
|
|
},
|
|
onReady() {
|
|
console.log("页面初次渲染完成");
|
|
this.initAliveDetect()
|
|
},
|
|
onBackPress() {
|
|
this.$refs.aliveDetect.stopDetect()
|
|
},
|
|
onUnload() {
|
|
console.log("页面卸载");
|
|
if (innerAudioContext != null && !innerAudioContext.paused) {
|
|
innerAudioContext.pause()
|
|
innerAudioContext.stop()
|
|
innerAudioContext.destroy()
|
|
innerAudioContext = null
|
|
}
|
|
this.timer && clearInterval(this.timer)
|
|
},
|
|
methods: {
|
|
initAliveDetect() {
|
|
this.timer && (clearInterval(this.timer))
|
|
this.curAction = {
|
|
step: 0,
|
|
tip: '',
|
|
image: 'pic_front.png'
|
|
}
|
|
this.$refs.aliveDetect.init({
|
|
'businessID': '043948b2576b41dc9d23d14b4e500b7a',
|
|
'timeout': 60,
|
|
'isDebug': true
|
|
}, this.handleCheck)
|
|
this.$refs.aliveDetect.startDetect()
|
|
this.restSec = 60
|
|
this.timer = setInterval(() => {
|
|
if (this.restSec <= 0) {
|
|
clearInterval(this.timer)
|
|
this.timer = null
|
|
} else {
|
|
this.restSec = this.restSec - 1
|
|
}
|
|
}, 1000)
|
|
|
|
// nvue不支持css animatin和uni的animation,所以使用weex内置的动画
|
|
animation.transition(this.$refs.leftCircle, {
|
|
styles: {
|
|
transform: 'rotate(135deg)'
|
|
},
|
|
duration: 15000,
|
|
timingFunction: 'linear',
|
|
needLayout: false,
|
|
delay: 15000
|
|
})
|
|
animation.transition(this.$refs.rightCircle, {
|
|
styles: {
|
|
transform: 'rotate(225deg)'
|
|
},
|
|
duration: 15000,
|
|
timingFunction: 'linear',
|
|
needLayout: false,
|
|
delay: 0
|
|
})
|
|
},
|
|
//去登录
|
|
async toReg(token) {
|
|
const res = await api.realNameAuth({
|
|
userId: uni.getStorageSync("userInfo").id,
|
|
realName: this.realName,
|
|
idCard: this.idCard,
|
|
token
|
|
})
|
|
console.log({
|
|
userId: uni.getStorageSync("userInfo").id,
|
|
realName: this.realName,
|
|
idCard: this.idCard,
|
|
token
|
|
})
|
|
console.log(res)
|
|
if(res.code == 200){
|
|
uni.showToast({
|
|
title: "提交成功"
|
|
})
|
|
setTimeout(()=>{
|
|
uni.navigateBack({
|
|
delta: 2
|
|
})
|
|
},2000)
|
|
}else{
|
|
uni.showToast({
|
|
icon: "none",
|
|
position: "bottom",
|
|
title: res.msg
|
|
})
|
|
}
|
|
},
|
|
handleCheck(ev) {
|
|
// 初始化活体检测引擎成功
|
|
if (typeof ev !== 'object') {
|
|
return
|
|
}
|
|
|
|
const method = ev['method']
|
|
const data = ev['data']
|
|
|
|
if (method == "onReady") {
|
|
const result = data['initResult']
|
|
console.log(result ? "引擎初始化成功" : "引擎初始化失败")
|
|
} else if (method == "onConfig") {
|
|
// 动作序列
|
|
let commands = [];
|
|
for (let i = 0; i < data['actions'].length; i++) {
|
|
commands.push(parseInt(data['actions'][i]))
|
|
};
|
|
this.commands = commands;
|
|
} else if (method == "onChecking") {
|
|
// 检测提示
|
|
const actionType = data['currentStep'] + ''
|
|
if (Object.keys(DETECT_ACTION_TYPES).includes(actionType) &&
|
|
actionType !== this.curAction.type) {
|
|
const hit = DETECT_ACTION_TYPES[actionType]
|
|
this.curAction = {
|
|
step: this.curAction.step + 1,
|
|
type: actionType,
|
|
tip: hit[0],
|
|
image: hit[1]
|
|
}
|
|
// console.log(this.curAction)
|
|
// console.log(data)
|
|
this.playAudioIfEnable(hit[2])
|
|
}
|
|
} else if (method == "onChecked") {
|
|
// // 检测结果
|
|
console.log(data)
|
|
this.toReg(data.token)
|
|
clearInterval(this.timer)
|
|
this.timer = null
|
|
return
|
|
} else if (method == "onError") {
|
|
// 检测失败
|
|
// console.log("错误码为:" + data['code']);
|
|
// console.log("错误信息为:" + data['message']);
|
|
uni.showToast({
|
|
icon: 'none',
|
|
position: "bottom",
|
|
title: data['message']
|
|
})
|
|
} else if (method == "overTime") {
|
|
// 超时
|
|
clearInterval(this.timer)
|
|
this.timer = null
|
|
uni.showModal({
|
|
title: '检测超时',
|
|
content: '请在规定时间内完成动作',
|
|
cancelText: '返回上一页',
|
|
confirmText: '重试',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
this.initAliveDetect()
|
|
} else {
|
|
uni.navigateBack()
|
|
}
|
|
},
|
|
fail: () => {
|
|
uni.navigateBack()
|
|
}
|
|
})
|
|
}
|
|
},
|
|
playAudioIfEnable(src) {
|
|
if (!this.enableAudio) return
|
|
innerAudioContext.src = `/static/shibie/audio/${src}`
|
|
innerAudioContext.play()
|
|
},
|
|
toggleAudioSwitch() {
|
|
this.enableAudio = !this.enableAudio
|
|
},
|
|
handleImgLoad() {
|
|
setTimeout(() => {
|
|
this.maskColor = 'transparent'
|
|
}, 120)
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.yd-check {
|
|
background-color: #ffffff;
|
|
}
|
|
|
|
.check-preview {
|
|
align-items: center;
|
|
justify-content: center;
|
|
position: relative;
|
|
}
|
|
|
|
.check-preview__content {
|
|
width: 504rpx;
|
|
height: 672rpx;
|
|
margin-top: 6rpx;
|
|
position: relative;
|
|
margin-top: 20rpx;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.check-preview__mask {
|
|
width: 504rpx;
|
|
height: 672rpx;
|
|
position: absolute;
|
|
display: block;
|
|
top: 0;
|
|
left: 0;
|
|
z-index: 55;
|
|
transition: backgroundColor 0.3s;
|
|
background-color: #ffffff;
|
|
}
|
|
|
|
.check-preview__camera {
|
|
width: 504rpx;
|
|
height: 672rpx;
|
|
border-radius: 50%;
|
|
margin-top: 20rpx;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.check-preview__audio {
|
|
position: absolute;
|
|
top: 0;
|
|
right: 40rpx;
|
|
width: 48rpx;
|
|
height: 48rpx;
|
|
}
|
|
|
|
.check-preview__switch {
|
|
width: 48rpx;
|
|
height: 48rpx;
|
|
}
|
|
|
|
.check-preview__timer {
|
|
position: absolute;
|
|
top: 80rpx;
|
|
right: 40rpx;
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
line-height: 60rpx;
|
|
color: #222;
|
|
font-size: 26rpx;
|
|
justify-content: center;
|
|
align-items: center;
|
|
.txt{
|
|
font-size: 26rpx;
|
|
color: #000;
|
|
}
|
|
}
|
|
|
|
.progress-timer__right,
|
|
.progress-timer__left {
|
|
width: 30rpx;
|
|
height: 60rpx;
|
|
position: absolute;
|
|
top: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.progress-timer__right {
|
|
right: 0;
|
|
}
|
|
|
|
.progress-timer__left {
|
|
left: 0;
|
|
}
|
|
|
|
.progress-timer__circle {
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
border-style: solid;
|
|
border-width: 6rpx;
|
|
border-color: #000000;
|
|
border-radius: 50%;
|
|
position: absolute;
|
|
top: 0;
|
|
}
|
|
|
|
.progress-timer__circle--right {
|
|
border-right-color: #ccc;
|
|
border-top-color: #ccc;
|
|
right: 0;
|
|
transform: rotate(45deg);
|
|
}
|
|
|
|
.progress-timer__circle--left {
|
|
border-left-color: #ccc;
|
|
border-top-color: #ccc;
|
|
left: 0;
|
|
transform: rotate(-45deg);
|
|
}
|
|
|
|
.check-process {
|
|
padding-top: 90rpx;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.check-process__tip {
|
|
opacity: 0.85;
|
|
font-size: 40rpx;
|
|
color: #000;
|
|
text-align: center;
|
|
line-height: 56rpx;
|
|
height: 56rpx;
|
|
}
|
|
|
|
.check-process__img {
|
|
width: 280rpx;
|
|
height: 280rpx;
|
|
margin-top: 8rpx;
|
|
text-align: center;
|
|
}
|
|
|
|
.check-steps {
|
|
flex-direction: row;
|
|
justify-content: space-around;
|
|
align-items: center;
|
|
width: 240rpx;
|
|
margin-top: 32rpx;
|
|
}
|
|
|
|
.check-steps__item {
|
|
font-size: 0px;
|
|
width: 20rpx;
|
|
height: 20rpx;
|
|
background-color: #DDE3EF;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.check-steps__item--active {
|
|
width: 40rpx;
|
|
height: 40rpx;
|
|
background-color: #000000;
|
|
justify-content: center;
|
|
}
|
|
|
|
.check-steps__text {
|
|
color: #FFFFFF;
|
|
line-height: 40rpx;
|
|
font-size: 28rpx;
|
|
text-align: center;
|
|
}
|
|
</style>
|
|
|