| | |
| | | <template> |
| | | <view class="container"> |
| | | <button class="scan" @click="openQrcode">点击扫码</button> |
| | | <view class="reader-box" v-if="isScaning"> |
| | | <view class="reader" id="reader"></view> |
| | | <view> |
| | | <cu-custom :bgColor="NavBarColor" :isBack="true" backRouterName="index"> |
| | | <block slot="backText">返回</block> |
| | | <block slot="content">扫一扫</block> |
| | | </cu-custom> |
| | | <view class="scanCode"> |
| | | <mumu-get-qrcode :continue="true" @success='qrcodeSucess' @error="qrcodeError" |
| | | :definition="true"></mumu-get-qrcode> |
| | | </view> |
| | | <view>扫码内容:{{scanVal}}</view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { |
| | | Html5Qrcode |
| | | } from "html5-qrcode"; |
| | | import mumuGetQrcode from '@/uni_modules/mumu-getQrcode/components/mumu-getQrcode/mumu-getQrcode.vue'; |
| | | |
| | | export default { |
| | | components: { |
| | | mumuGetQrcode // 注册 |
| | | }, |
| | | name: 'spare', |
| | | watch: { |
| | | cur: { |
| | | immediate: true, |
| | | handler() { |
| | | console.log('watch', this.cur) |
| | | }, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | html5QrCode: null, |
| | | isScaning: false, |
| | | cameraId: null, |
| | | scanVal: '' |
| | | } |
| | | NavBarColor: this.NavBarColor, |
| | | hasNavigated: false // 标记是否已经跳转 |
| | | }; |
| | | }, |
| | | methods: { |
| | | |
| | | isValidURL(url) { |
| | | const pattern = new RegExp('^(https?:\\/\\/)?' + // protocol |
| | | '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name |
| | | '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address |
| | | '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path |
| | | '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string |
| | | '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator |
| | | return !!pattern.test(url); |
| | | }, |
| | | checkURL() { |
| | | const url = this.scanVal; |
| | | if (this.isValidURL(url)) { |
| | | uni.openURL({ |
| | | url: url |
| | | }) |
| | | } else { |
| | | uni.showToast({ |
| | | title: 'url地址错误,请重试', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | openQrcode() { |
| | | this.isScaning = true; |
| | | Html5Qrcode.getCameras().then((devices) => { |
| | | if (devices && devices.length) { |
| | | if (devices.length > 1) { |
| | | this.cameraId = devices[1].id; |
| | | } else { |
| | | this.cameraId = devices[0].id; |
| | | } |
| | | this.html5QrCode = new Html5Qrcode('reader'); |
| | | this.startInit(); |
| | | } |
| | | }); |
| | | }, |
| | | startInit() { |
| | | const that = this; |
| | | this.html5QrCode.start( |
| | | this.cameraId, // retreived in the previous step. |
| | | // { |
| | | // facingMode: "environment" // environment后置摄像头 user前置摄像头 |
| | | // mounted() { |
| | | // window.addEventListener('hashchange', this.handleHashChange); |
| | | // // 初始解析 hash |
| | | // this.handleHashChange(); |
| | | // }, |
| | | { |
| | | fps: 10, // sets the framerate to 10 frame per second |
| | | qrbox: 250 // sets only 250 X 250 region of viewfinder to |
| | | // beforeDestroy() { |
| | | // window.removeEventListener('hashchange', this.handleHashChange); |
| | | // }, |
| | | |
| | | methods: { |
| | | // handleHashChange() { |
| | | // if (this.hasNavigated) { |
| | | // console.log('Already navigated, skipping hash change handling'); |
| | | // return; |
| | | // } |
| | | |
| | | // const hash = window.location.hash; |
| | | // console.log('Hash changed:', hash); // 添加日志 |
| | | // if (!hash || hash.length === 0) { |
| | | // console.warn('Hash is empty or undefined'); |
| | | // return; |
| | | // } |
| | | // const params = new URLSearchParams(hash.split('?')[1]); |
| | | // const equipmentId = params.get('equipmentId'); |
| | | // console.log('Parsed equipmentId:', equipmentId); // 添加日志 |
| | | // if (equipmentId) { |
| | | // this.navigateToDeviceDetails(equipmentId); |
| | | // } else { |
| | | // console.warn('No equipmentId found in hash'); |
| | | // } |
| | | // }, |
| | | navigateToDeviceDetails(equipmentId) { |
| | | this.hasNavigated = true; // 标记已经跳转 |
| | | uni.navigateTo({ |
| | | url: `/pages/device/deviceWebDeils/deviceWebDeils?equipmentId=${encodeURIComponent(equipmentId)}`, |
| | | success: () => { |
| | | console.log('Navigated to device details'); |
| | | }, |
| | | qrCodeMessage => { |
| | | fail: (err) => { |
| | | console.error('Navigation failed:', err); |
| | | } |
| | | }); |
| | | }, |
| | | qrcodeSucess(data) { // 扫码成功 |
| | | setTimeout(() => { |
| | | let equipmentId; |
| | | try { |
| | | // 兼容性处理:优先使用URL和URLSearchParams,如果不可用则使用字符串解析 |
| | | if ('URL' in window && 'URLSearchParams' in window) { |
| | | const url = new URL(data); |
| | | const params = new URLSearchParams(url.hash.slice(1).split('?')[1]); |
| | | equipmentId = params.get('equipmentId'); |
| | | } else { |
| | | // 字符串解析方式 |
| | | const hashIndex = data.indexOf('#'); |
| | | if (hashIndex !== -1) { |
| | | const hashPart = data.substring(hashIndex + 1); |
| | | const paramIndex = hashPart.indexOf('?'); |
| | | if (paramIndex !== -1) { |
| | | const paramStr = hashPart.substring(paramIndex + 1); |
| | | const pairs = paramStr.split('&'); |
| | | for (let pair of pairs) { |
| | | const [key, value] = pair.split('='); |
| | | if (key === 'equipmentId') { |
| | | equipmentId = value; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (equipmentId) { |
| | | // 登录成功且获取到equipmentId,跳转到设备详情页面 |
| | | this.navigateToDeviceDetails(equipmentId); |
| | | } else { |
| | | uni.showModal({ |
| | | title: 'success', |
| | | content: JSON.stringify(qrCodeMessage), |
| | | title: '提示', |
| | | content: "二维码中未找到有效的equipmentId", |
| | | showCancel: false |
| | | }); |
| | | // do something when code is read. For example: |
| | | if (qrCodeMessage) { |
| | | //成功扫出码qrCodeMessage为扫码内容 |
| | | //扫码成功记得关掉摄像 |
| | | that.action(qrCodeMessage) //对二维码逻辑处理 |
| | | that.stopScan(); //关闭扫码功能 |
| | | } |
| | | |
| | | } catch (error) { |
| | | uni.showModal({ |
| | | title: '错误', |
| | | content: "解析URL出错,请检查二维码内容", |
| | | showCancel: false |
| | | }); |
| | | } |
| | | }, 200); // 增加100毫秒的延迟 |
| | | }, |
| | | errorMessage => { |
| | | console.log('errorMessage', errorMessage); |
| | | if (errorMessage.includes('NotFoundException')) { |
| | | uni.showToast({ |
| | | title: '未找到二维码,请重新对准', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | } else { |
| | | uni.showToast({ |
| | | title: '扫码失败,请重试', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | qrcodeError(err) { // 扫码失败 |
| | | uni.showModal({ |
| | | title: '摄像头授权失败', |
| | | content: '摄像头授权失败,请检测当前浏览器是否有摄像头权限。', |
| | | success: () => { |
| | | uni.navigateBack({}); // 返回到上一页 |
| | | } |
| | | }); |
| | | } |
| | | |
| | | } |
| | | ) |
| | | .catch((err) => { |
| | | // 扫码错误信息 |
| | | let message = ""; |
| | | if (typeof err == "string") { |
| | | message = "识别失败"; |
| | | } else { |
| | | if (err.name == "NotAllowedError") { |
| | | message = "您需要授予相机访问权限!"; |
| | | } |
| | | if (err.name == "NotFoundError") { |
| | | message = "这个设备上没有摄像头!"; |
| | | } |
| | | if (err.name == "NotSupportedError") { |
| | | message = |
| | | "摄像头访问只支持在安全的上下文中,如https或localhost!"; |
| | | } |
| | | if (err.name == "NotReadableError") { |
| | | message = "相机被占用!"; |
| | | } |
| | | if (err.name == "OverconstrainedError") { |
| | | message = "安装摄像头不合适!"; |
| | | } |
| | | if (err.name == "StreamApiNotSupportedError") { |
| | | message = "此浏览器不支持流API!"; |
| | | } |
| | | } |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | }); |
| | | }, |
| | | action(val) { |
| | | this.scanVal = val; |
| | | const url = this.scanVal; |
| | | this.checkURL(url) |
| | | |
| | | // plus.runtime.openURL(this.scanVal, function(res) { |
| | | // console.log(res); |
| | | // }); |
| | | }, |
| | | stopScan() { |
| | | console.log('停止扫码') |
| | | this.isScaning = false; |
| | | if (this.html5QrCode) { |
| | | this.html5QrCode.stop() |
| | | .then((ignore) => { |
| | | console.log("停止扫码", ignore); |
| | | }) |
| | | .catch((err) => { |
| | | console.log(err); |
| | | showToast("停止扫码失败"); |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | .container { |
| | | .scanCode { |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | z-index: 99; |
| | | height: 100%; |
| | | width: 100%; |
| | | background-color: rgba(0, 0, 0, 0.7); |
| | | } |
| | | |
| | | .reader-box { |