index.vue 7.43 KB
<!--
 * @Date: 2024-01-26 13:08:09
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2026-02-02 16:02:52
 * @FilePath: /xyxBooking-weapp/src/pages/search/index.vue
 * @Description: 搜索页
-->
<template>
  <view class="search-page">
    <view>
      <view v-if="!is_search">
        <view class="input-card" @tap="open_id_type_picker">
          <view class="input-label">证件类型</view>
          <view class="picker-value">
            <text>{{ id_type_label }}</text>
            <text class="picker-arrow">›</text>
          </view>
        </view>
        <view class="input-card">
          <view class="input-label">证件号码</view>
          <input
            class="id-input"
            type="text"
            v-model="idCode"
            placeholder="请输入证件号码"
            @blur="checkIdCode"
            :maxlength="id_type === 1 ? 18 : 30"
          />
        </view>
        <view class="tip-block">
          <view class="tip-title">
            <IconFont name="tips" size="16" color="#A67939" />
            <text class="tip-title-text">温馨提示</text>
          </view>
          <view class="tip-desc">获取参观码,扫码或识别身份证成功进闸机</view>
        </view>
      </view>
      <view v-else>
        <qrCodeSearch :id="id_number" :id_type="id_type" />
      </view>
    </view>
    <view class="logo"></view>

    <view v-if="!is_search" class="footer">
      <view class="footer-btn" @tap="searchBtn">查询</view>
    </view>
    <view v-else class="success-footer">
      <view @tap="goToHome" class="btn-item btn-left">首页</view>
      <view @tap="goBack" class="btn-item btn-right">返回查询</view>
    </view>
  </view>

  <nut-popup v-model:visible="show_id_type_picker" position="bottom" safe-area-inset-bottom>
    <nut-picker
      v-model="id_type_picker_value"
      :columns="id_type_columns"
      title="选择证件类型"
      @confirm="on_id_type_confirm"
      @cancel="show_id_type_picker = false"
    ></nut-picker>
  </nut-popup>

  <PrivacyPopup
    v-model:visible="showPrivacyPopup"
    @agree="onPrivacyAgree"
    @disagree="onPrivacyDisagree"
  />
</template>

<script setup>
import { ref, computed } from 'vue'
import Taro, { useDidShow } from '@tarojs/taro'
import { IconFont } from '@nutui/icons-vue-taro'
import qrCodeSearch from '@/components/qrCodeSearch'
import PrivacyPopup from '@/components/PrivacyPopup.vue'
import { useGo } from '@/hooks/useGo'
import { showError } from '@/utils/toast'

const go = useGo()
const is_search = ref(false)
const idCode = ref('')
const id_number = ref('')
const show_id_type_picker = ref(false)
const showPrivacyPopup = ref(false)

useDidShow(() => {
  const hasAgreed = Taro.getStorageSync('HAS_AGREED_PRIVACY')
  if (!hasAgreed) {
    showPrivacyPopup.value = true
  }
})

/**
 * @description 隐私协议同意回调
 */
const onPrivacyAgree = () => {
  Taro.setStorageSync('HAS_AGREED_PRIVACY', true)
  showPrivacyPopup.value = false
}

/**
 * @description 隐私协议拒绝回调
 */
const onPrivacyDisagree = () => {
  const pages = Taro.getCurrentPages()
  if (pages.length > 1) {
    Taro.navigateBack()
  } else {
    // 如果是首个页面,跳转到首页
    Taro.reLaunch({ url: '/pages/index/index' })
  }
}
const id_type_options = [
  { label: '身份证', value: 1 },
  { label: '其他', value: 3 }
]
const id_type = ref(id_type_options[0].value)
const id_type_picker_value = ref([String(id_type.value)])

const id_type_columns = computed(() => {
  return id_type_options.map(item => ({
    text: item.label,
    value: String(item.value)
  }))
})
const id_type_label = computed(() => {
  return (
    id_type_options.find(item => item.value === id_type.value)?.label || id_type_options[0].label
  )
})

const open_id_type_picker = () => {
  id_type_picker_value.value = [String(id_type.value)]
  show_id_type_picker.value = true
}

const on_id_type_confirm = ({ selectedValue }) => {
  const value = selectedValue?.[0]
  id_type.value = Number(value) || 1
  show_id_type_picker.value = false
}

// 简单的身份证校验
const validateCIN = id => {
  return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(id)
}

const checkIdCode = () => {
  // 检查身份证号是否为空
  if (id_type.value !== 1) {
    return true
  }

  let flag = true
  if (idCode.value.length === 15) {
    // 15位身份证号码不校验
    flag = true
  } else {
    if (!validateCIN(idCode.value)) {
      showError('请检查身份证号码')
      flag = false
    }
  }
  return flag
}

const searchBtn = async () => {
  // 查询用户信息
  if (checkIdCode() && idCode.value) {
    is_search.value = true
    id_number.value = idCode.value
    idCode.value = ''
  }
}
const goBack = () => {
  is_search.value = false
}
const goToHome = () => {
  go('/index')
}
</script>

<style lang="less">
.search-page {
  position: relative;
  min-height: 100vh;
  padding: 32rpx;
  padding-bottom: 220rpx;
  background-image: url('https://cdn.ipadbiz.cn/xys/booking/bg.jpg');
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;

  .input-card {
    background-color: #fff;
    border-radius: 16rpx;
    border: 2rpx solid rgba(166, 121, 57, 0.45);
    margin-bottom: 32rpx;
    height: 112rpx;
    display: flex;
    align-items: center;
    padding: 0 32rpx;

    .input-label {
      width: 160rpx;
      color: #333;
      font-size: 30rpx;
      font-weight: 600;
    }

    .id-input {
      flex: 1;
      width: 100%;
      text-align: right;
      font-size: 30rpx;
      color: #333;
    }

    .picker-value {
      flex: 1;
      display: flex;
      align-items: center;
      justify-content: flex-end;
      text-align: right;
      font-size: 30rpx;
      color: #333;
    }

    .picker-arrow {
      margin-left: 10rpx;
      color: #bbb;
      font-size: 28rpx;
    }
  }

  .tip-block {
    margin-top: 64rpx;
    color: #a67939;
    text-align: center;
    font-size: 30rpx;

    .tip-title {
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .tip-title-text {
      margin-left: 10rpx;
      font-weight: 600;
    }

    .tip-desc {
      margin-top: 16rpx;
      font-weight: 600;
    }
  }

  .footer {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 24rpx 32rpx calc(24rpx + env(safe-area-inset-bottom));
  }

  .footer-btn {
    background-color: #a67939;
    color: #fff;
    text-align: center;
    height: 96rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 12rpx;
    font-size: 34rpx;
    font-weight: 600;
  }

  .success-footer {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 24rpx 32rpx calc(24rpx + env(safe-area-inset-bottom));
    display: flex;
    gap: 24rpx;

    .btn-item {
      flex: 1;
      text-align: center;
      height: 96rpx;
      display: flex;
      align-items: center;
      justify-content: center;
      border-radius: 12rpx;
      font-size: 34rpx;
      font-weight: 600;
    }

    .btn-left {
      border: 2rpx solid #a67939;
      color: #a67939;
      background-color: #fff;
    }

    .btn-right {
      background-color: #a67939;
      color: #fff;
    }
  }

  .logo {
    position: absolute;
    right: 0;
    bottom: 240rpx;
    height: 400rpx;
    width: 150rpx;
    background-image: url('https://cdn.ipadbiz.cn/xys/booking/logo.png');
    background-repeat: no-repeat;
    background-size: contain;
    background-position: center;
    opacity: 0.5;
    pointer-events: none;
  }
}
</style>