123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- <script setup>
- definePageMeta({
- layout: 'scan'
- })
- import {Html5Qrcode, Html5QrcodeSupportedFormats} from "html5-qrcode";
- const router = useRouter()
- const emit = defineEmits('oSuccess', 'onError')
- let scanInstance = null; // 扫码实例
- let results = ref(null); // 扫码结果
- const initScanInstance = () => {
- if (!scanInstance) {
- // reader放置扫码功能的元素ID
- scanInstance = new Html5Qrcode('qr-reader', {
- formatsToSupport: [
- Html5QrcodeSupportedFormats.QR_CODE,
- ],
- })
- }
- }
- const openQrcode = async () => {
- Html5Qrcode.getCameras()
- .then(devices => {
- if (devices && devices.length) {// 当前环境下能识别出摄像头,并且摄像头的数据可能不止一个
- initScanInstance()
- scanInstance.start(
- {facingMode: "environment"},
- {
- focusMode: 'continuous',
- fps: 1, // 可选,每n秒帧扫描一次
- qrbox: { // 扫描的UI框
- width: 250,
- height: 250
- },
- videoConstraints: {
- // width: 375,
- // height: (window.visualViewport.height - 50),
- aspectRatio: window.visualViewport.height / window.visualViewport.width,
- facingMode: "environment",
- }
- },
- (decodedText, decodedResult) => {
- showToast('识别成功')
- handleSuccess({decodedText, decodedResult})
- },
- (errorMessage, error) => {
- closeQrcode(errorMessage)
- }
- )
- }
- })
- .catch((err) => {
- // 错误信息处理仅供参考,具体情况看输出!!!
- let errorStr = ''
- if (typeof err === "string") {
- errorStr = err
- } else {
- if (err.name === "NotAllowedError")
- errorStr = "您需要授予相机访问权限"
- if (err.name === "NotFoundError") {
- errorStr = "未检测到摄像头"
- }
- if (err.name === "NotSupportedError")
- errorStr = "摄像头访问只支持在安全的上下文中,如https或localhost"
- if (err.name === "NotReadableError") errorStr = "摄像头被占用"
- if (err.name === "OverconstrainedError")
- errorStr = "安装摄像头不合适"
- if (err.name === "StreamApiNotSupportedError")
- errorStr = "此浏览器不支持流API"
- }
- showToast(errorStr)
- })
- }
- const scanLoadImg = (e) => {
- try {
- initScanInstance()
- scanInstance.scanFile(e.file, false)
- .then(result => {
- // 二维码结果
- console.log(result, '上传扫码成功')
- handleSuccess(result)
- })
- .catch(err => {
- console.error(err, '上传扫码失败')
- })
- } catch (e) {
- console.error(e, '失败')
- }
- }
- const getResults = (result) => {
- if (!result) {
- return {success: false, groupId: null, overTime: false}
- }
- const url = new URL(result);
- const urlParams = new URLSearchParams(url.search);
- const hasGroupId = urlParams.has('groupId');
- const hasTime = urlParams.has('time');
- console.log(url.search, hasGroupId, hasTime, 'hasTime')
- if (!hasGroupId || !hasTime) {
- return {success: false, groupId: null, overTime: false}
- }
- const givenDate = new Date(urlParams.get('time'));
- const currentDate = new Date();
- const givenDateCst = new Date(givenDate.getTime() + (8 * 60 * 60 * 1000));
- const currentDateCst = new Date(currentDate.getTime() + (8 * 60 * 60 * 1000));
- const diffInMilliseconds = currentDateCst - givenDateCst;
- const sevenDaysInMilliseconds = 7 * 24 * 60 * 60 * 1000;
- return {
- success: true,
- groupId: urlParams.get('groupId'),
- overTime: diffInMilliseconds > sevenDaysInMilliseconds
- }
- }
- const handleSuccess = (result) => {
- results.value = result
- router.replace({
- path: '/chat/qr-results',
- query: result ? getResults(result) : result
- })
- }
- const closeQrcode = () => {
- if (scanInstance && scanInstance.isScanning) scanInstance.stop()
- router.back()
- }
- onMounted(async () => {
- initScanInstance()
- await nextTick()
- await openQrcode()
- })
- onUnmounted(() => {
- if (scanInstance && scanInstance.isScanning) scanInstance.stop()
- })
- </script>
- <template>
- <div>
- <div v-if="false" class="h-200">
- {{ results }}
- </div>
- <div class="overlay">
- <div class="absolute w-full z-30 flex flex-row items-center justify-center p-12">
- <div class="absolute left-12 font-bold" @click="closeQrcode">
- <span class="iconfont icon-left text-white"></span>
- </div>
- <div class="text-base text-[#fff] font-bold">
- 扫描二维码
- </div>
- </div>
- <div class="relative qr-reader z-20" id="qr-reader"></div>
- <p class="absolute w-full p-12 text-center bottom-100 z-30 text-sm text-[#fff]">请将二维码对准扫码框中心</p>
- <div id="qr-code-file"
- class="absolute w-54 h-54 grid place-items-center bottom-40 z-30 rounded-full bg-[#000]/80 text-white left-1/2 -translate-x-1/2">
- <van-uploader
- :preview-image="false"
- :after-read="scanLoadImg"
- accept="image/*"
- :multiple="false"
- :max-count="1"
- ><img src="~/assets/img/scan/pic.png" height="32" width="32" alt=""/>
- </van-uploader>
- </div>
- </div>
- </div>
- </template>
- <style scoped lang="scss">
- .overlay {
- position: fixed;
- bottom: 0;
- left: 0;
- z-index: 999999;
- width: 100%;
- height: 100%;
- background: rgba(0, 0, 0, 0.7);
- }
- </style>
|