<template>
<div class="sampling-registration">
<div class="container">
<div class="content">
<img class="sampling-icon" src="@pages/pink-ribbon/assets/imgs/sampling/sampling-icon.png" />
<div class="input-box">
<input placeholder="请输入采样条形码" v-model="barcode" />
</div>
<div class="scan" @click="startScan">
<img src="@pages/pink-ribbon/assets/imgs/sampling/camera-icon.png" class="scan-icon" />
扫码识别
</div>
</div>
<div class="agree" :class="{ 'shake-animation': shakeAnimation }" @click="switchAgree">
<div class="radio-btn" :class="{ 'radio-btn-active': agreeChecked, 'radio-btn-default': !agreeChecked }"></div>
<span class="agree-text"
>请务必确认采样信息登记时的信息与实际采样人一致,检测报告仅对本次实际采样人送检样本负责</span
>
</div>
</div>
<div id="interactive" v-show="isScanningFlag">
<img @click.stop="stopScan" class="close_icon" src="@pages/pink-ribbon/assets/imgs/sampling/close_icon.png" />
</div>
</div>
</template>
<script lang="ts" setup>
import { showToast } from 'vant'
import { useRouter, useRoute, LocationQueryValue } from 'vue-router'
import { save } from './service'
import { ref, onMounted, onUnmounted } from 'vue'
import Quagga from '@ericblade/quagga2'
import { isEmpty } from 'lodash'
import { useUserStore } from '@pink/store/user'
import { handleDeniedPermission } from '@/JSBridge/hooks/useDeniedPermission'
import { rnScanQrcode, rnIsShowTab, rnAndroidScanQrcode, rnGoThirdpage } from '@JSBridge/nativeOperations'
import { useService } from '@JSBridge/hooks/useService'
import { isIOS, isWechatMiniEnv, isInAppAndroid, isInApp } from '@JSBridge/hooks/useBridgeUtils'
import config from '@pink/config'
import { jsbridge } from '@hhorg/hh-sdk'
const { token, userInfo } = storeToRefs(useUserStore())
const barcode = ref(null)
const isScanning = ref(false)
const isScanningFlag = ref(false)
const agreeChecked = ref(false)
const shakeAnimation = ref(false)
const router = useRouter()
const route = useRoute()
const age = route.query.age ?? ''
const right_name = route.query.right_name ?? ''
const gender = route.query.gender ?? ''
const name = route.query.name ?? ''
const isShowKeyBoard = ref(false)
const startScan = () => {
if (jsbridge.isWxWebEnv()) {
isScanningFlag.value = true
if (isScanning.value) return
console.log('666')
console.log(666)
Quagga.init(
{
inputStream: {
type: 'LiveStream',
constraints: {
width: { ideal: window.innerWidth },
height: window.innerHeight,
facingMode: 'environment'
},
target: document.querySelector('#interactive')
},
decoder: {
readers: ['code_128_reader', 'ean_reader', 'ean_8_reader', 'upc_reader', 'code_39_reader']
}
},
(err) => {
if (err) {
console.error(err)
return
}
isScanning.value = true
Quagga.start()
attachListeners()
}
)
} else if (isIOS()) {
handleIOSScan()
} else {
console.log('Androif==== >', isInAppAndroid())
handleAndroidScan()
}
}
const switchAgree = () => {
agreeChecked.value = !agreeChecked.value
}
const handleAndroidScan = async () => {
console.log('点击----》》》')
let resultObj: any = await rnAndroidScanQrcode()
console.log('Android ====>', resultObj)
}
const setIsShowTab = async (isShow: boolean) => {
await rnIsShowTab(isShow)
}
const handleIOSScan = async () => {
let resultObj: any = await rnScanQrcode()
console.log('resultObj========<><><>', resultObj)
if (resultObj && !isEmpty(resultObj)) {
barcode.value = resultObj.result
} else {
const payloadObj = {
payload: {
value: '',
type: ''
}
}
payloadObj.payload.value = resultObj?.value
payloadObj.payload.type = resultObj?.type
handleDeniedPermission(payloadObj)
}
}
const attachListeners = () => {
Quagga.onDetected((data) => {
barcode.value = data.codeResult.code
console.log('Detected barcode:', data.codeResult.code)
Quagga.stop()
isScanning.value = false
isScanningFlag.value = false
})
}
const stopScan = () => {
if (isScanning.value) {
Quagga.stop()
isScanning.value = false
isScanningFlag.value = false
}
}
const next = async () => {
if (!agreeChecked.value) {
showToast('请先确认登记信息')
shakeAnimation.value = true
let timer = setTimeout(() => {
shakeAnimation.value = false
clearTimeout(timer)
}, 500)
return
}
if (!barcode.value) {
showToast('采样码不能为空')
return
}
const order_id = route.query.order_id ?? ''
const card_id = barcode.value
const params = {
card_id,
order_id
}
const { data } = await save(params)
if (data.status !== 200) {
showToast(data.message)
} else {
jumpToTencentQuestion(order_id, card_id)
}
}
const jumpToTencentQuestion = (order_id: string | LocationQueryValue[], card_id: string | null) => {
console.log('isWechatMiniEnv', isWechatMiniEnv())
if (isWechatMiniEnv()) {
console.log('order_id', order_id, card_id)
const url = `/pages/SurveyTransferPage?userId=${order_id}_${card_id}`
jsbridge.mini.goPage({
miniPath: url
})
} else if (jsbridge.isAppEnv()) {
const url = `${config.TencentQuestion}?userid=${order_id}_${card_id}`
window.location.replace(url)
} else {
const url = `${config.TencentQuestion}?userid=${order_id}_${card_id}`
window.location.replace(url)
}
}
const onKeyBoardUp = () => {
isShowKeyBoard.value = true
}
const onKeyBoardDown = () => {
isShowKeyBoard.value = false
}
onUnmounted(() => {
Quagga.stop()
})
onMounted(() => {
let originalHeight = document.documentElement.clientHeight || document.body.clientHeight
window.onresize = function () {
let resizeHeight = document.documentElement.clientHeight || document.body.clientHeight
if (resizeHeight - 0 < originalHeight - 0) {
onKeyBoardUp()
} else {
onKeyBoardDown()
}
}
})
const scanQrcodeCallBack = (data) => {
console.log('scanQrcodeCallBack ===>', data)
if (data.type === 'h5Scan') {
barcode.value = data.payload
}
}
useService('h5Scan', scanQrcodeCallBack)
useService('isDeniedPermission', handleDeniedPermission)
</script>
<style scoped lang="scss">
.sampling-registration {
// height: 100vh;
height: calc(100vh - 120px);
display: flex;
flex-direction: column;
font-family: PingFang SC, PingFang SC;
overflow-y: auto;
background: #f6f8f8;
box-sizing: border-box;
.container {
position: relative;
padding: 30px;
height: 100%;
// height: calc(100vh - 102px);
box-sizing: border-box;
}
.header {
padding: 30px;
min-height: 120px;
background: #ffffff;
border-radius: 36px 36px 36px 36px;
.title {
margin-bottom: 26px;
height: 42px;
font-weight: 600;
font-size: 15px;
color: #203042;
}
.item {
font-size: 14px;
.label {
display: inline-block;
width: 165px;
color: #647485;
}
.value {
color: #203042;
}
}
}
.content {
margin-top: 30px;
padding: 30px;
background: #ffffff;
border-radius: 36px 36px 36px 36px;
.input-box {
margin: 24px 0;
display: flex;
align-items: center;
justify-content: center;
input {
width: 100%;
height: 120px;
text-align: center;
font-size: 14px;
background: #f6f8f8;
border: none;
border-radius: 36px 36px 36px 36px;
}
}
.scan {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 90px;
font-size: 13px;
text-align: center;
line-height: 45px;
border-radius: 57px;
img {
width: 30px;
height: 30px;
margin-right: 10px;
}
}
img {
width: 100%;
height: 251px;
}
}
.footer {
position: fixed;
bottom: 0;
width: 100%;
padding-top: 12px;
padding-bottom: 44px;
display: flex;
align-items: center;
justify-content: center;
min-height: 94px;
background: #ffffff;
box-sizing: border-box;
.button {
width: 630px;
height: 70px;
line-height: 35px;
text-align: center;
font-size: 14px;
color: #ffffff;
background: #203042;
border-radius: 57px 57px 57px 57px;
}
}
.agree {
margin-top: 100px;
display: flex;
align-items: flex-start;
justify-content: center;
height: 72px;
font-weight: 400;
font-size: 13px;
color: #203042;
line-height: 15px;
.radio-btn {
margin-right: 14px;
display: inline-block;
flex-shrink: 0;
width: 30px;
height: 30px;
}
.radio-btn-default {
border: 3px solid rgba(32, 48, 66, 0.4);
border-radius: 100%;
box-sizing: border-box;
}
.radio-btn-active {
background-image: url('@pages/pink-ribbon/assets/imgs/sampling/checked.png');
background-size: 100% 100%;
}
}
}
@keyframes shake {
0% {
transform: translateX(0);
}
25% {
transform: translateX(-10px);
}
50% {
transform: translateX(10px);
}
75% {
transform: translateX(-10px);
}
100% {
transform: translateX(10px);
}
}
.shake-animation {
animation: shake 0.3s;
animation-iteration-count: infinite;
}
#interactive {
height: 100%;
position: absolute;
left: 0;
right: 0;
top: 0;
z-index: 99;
overflow: hidden;
:deep(video) {
height: 100vh;
}
.close_icon {
width: 46px;
height: 46px;
position: absolute;
top: 130px;
left: 50px;
z-index: 999;
}
}
</style>