支付宝上架
This commit is contained in:
@@ -585,7 +585,7 @@
|
||||
if (isWechatMiniProgram.value) {
|
||||
return t('device.rentDepositFree')
|
||||
} else {
|
||||
return '立即租借'
|
||||
return t('device.rentNow')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+184
-16
@@ -17,16 +17,11 @@
|
||||
</view>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<!-- #ifdef MP-ALIPAY -->
|
||||
<view class="main-content" :style="{ paddingTop: (navBarHeight + noticeHeight) + 'px' }">
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-ALIPAY -->
|
||||
<view class="main-content" :style="{ paddingTop: (statusBarHeight + navBarHeight + noticeHeight) + 'px' }">
|
||||
<!-- #endif -->
|
||||
<view class="main-content" :style="mainContentStyle">
|
||||
<!-- 全屏地图组件 -->
|
||||
<!-- 支付宝小程序使用专用组件 -->
|
||||
<!-- #ifdef MP-ALIPAY -->
|
||||
<MapComponentAlipay v-if="!isLoading && userLocation" ref="mapRef" :userLocation="userLocation"
|
||||
<MapComponentAlipay v-if="!isLoading && userLocation && !locationPermissionDenied" ref="mapRef" :userLocation="userLocation"
|
||||
:positionList="positionList" :filteredPositions="filteredPositions" :searchKeyword="searchKeyword"
|
||||
:enableMarkers="true" :bannerImages="bannerImages"
|
||||
:hideMapOverlays="showGuidePopup || showNoticePopup || showActivityPopup" @relocate="handleRelocate"
|
||||
@@ -35,7 +30,7 @@
|
||||
<!-- #endif -->
|
||||
<!-- 非支付宝小程序使用通用组件 -->
|
||||
<!-- #ifndef MP-ALIPAY -->
|
||||
<MapComponent v-if="!isLoading && userLocation" ref="mapRef" :userLocation="userLocation"
|
||||
<MapComponent v-if="!isLoading && userLocation && !locationPermissionDenied" ref="mapRef" :userLocation="userLocation"
|
||||
:positionList="positionList" :filteredPositions="filteredPositions" :searchKeyword="searchKeyword"
|
||||
:enableMarkers="true" :bannerImages="bannerImages"
|
||||
:hideMapOverlays="showGuidePopup || showNoticePopup || showActivityPopup" @relocate="handleRelocate"
|
||||
@@ -44,12 +39,26 @@
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- 地图加载状态 -->
|
||||
<!-- #ifdef MP-ALIPAY -->
|
||||
<view v-if="!userLocation" class="location-denied-placeholder">
|
||||
<view class="denied-content">
|
||||
<text class="denied-text">{{ $t('home.locationPermissionOffTip') }}</text>
|
||||
<view class="denied-enable-btn" @click="handleEnableLocation">
|
||||
<text class="denied-enable-btn-text">{{ $t('home.enableLocation') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 支付宝端:拒绝定位后直接展示提示;不展示 common.loadingLocation -->
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifndef MP-ALIPAY -->
|
||||
<view v-if="isLoading || !userLocation" class="map-loading-placeholder">
|
||||
<view class="loading-content">
|
||||
<view class="loading-spinner"></view>
|
||||
<text>{{ $t('common.loadingLocation') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
|
||||
<!-- 底部操作栏:附近设备 / 扫码使用 / 我的 -->
|
||||
@@ -282,6 +291,7 @@
|
||||
const filteredPositions = ref([])
|
||||
const isExpanded = ref(false)
|
||||
const isLoading = ref(false)
|
||||
const locationPermissionDenied = ref(false) // MP-ALIPAY:定位权限拒绝后展示引导文案
|
||||
const showPhoneAuthPopup = ref(false)
|
||||
const pendingScan = ref(false) // 是否是扫码流程触发的手机号校验
|
||||
const expectedUserPhone = ref('') // 当前登录态下绑定的手机号(用于支付宝一致性校验)
|
||||
@@ -324,6 +334,16 @@
|
||||
// #endif
|
||||
})
|
||||
|
||||
// 主内容区域样式:不同端适配不同的 paddingTop
|
||||
const mainContentStyle = computed(() => {
|
||||
// #ifdef MP-ALIPAY
|
||||
return { paddingTop: (navBarHeight.value + noticeHeight.value) + 'px' }
|
||||
// #endif
|
||||
// #ifndef MP-ALIPAY
|
||||
return { paddingTop: (statusBarHeight.value + navBarHeight.value + noticeHeight.value) + 'px' }
|
||||
// #endif
|
||||
})
|
||||
|
||||
// 使用指南步骤
|
||||
const guideSteps = ref([{
|
||||
title: '扫码使用',
|
||||
@@ -619,6 +639,7 @@
|
||||
|
||||
// 方法
|
||||
const init = async () => {
|
||||
locationPermissionDenied.value = false
|
||||
isLoading.value = true
|
||||
try {
|
||||
// 清理旧版本的缓存键(兼容性处理)
|
||||
@@ -651,6 +672,14 @@
|
||||
|
||||
} catch (error) {
|
||||
console.error('初始化失败:', error)
|
||||
// #ifdef MP-ALIPAY
|
||||
if (isLocationPermissionDenied(error)) {
|
||||
locationPermissionDenied.value = true
|
||||
userLocation.value = null
|
||||
positionList.value = []
|
||||
filteredPositions.value = []
|
||||
}
|
||||
// #endif
|
||||
// uni.showToast({
|
||||
// title: t('home.getLocationFailed'),
|
||||
// icon: 'none'
|
||||
@@ -660,6 +689,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
const isLocationPermissionDenied = (error) => {
|
||||
const msg = String(error?.errMsg || error?.message || error || '')
|
||||
// 覆盖常见文案:permission denied / auth deny / 拒绝 / 未授权
|
||||
return /permission\s*denied|auth\s*deny|auth\s*denied|denied|拒绝|未授权|not\s*allowed|not\s*permitted/i.test(msg)
|
||||
}
|
||||
|
||||
const getUserLocationAndAddress = async () => {
|
||||
// 使用腾讯地图SDK获取位置(若失败抛出,由调用方统一处理)
|
||||
const location = await getUserLocation()
|
||||
@@ -719,6 +754,55 @@
|
||||
return userLocation.value
|
||||
}
|
||||
|
||||
const handleEnableLocation = async () => {
|
||||
isLoading.value = true
|
||||
try {
|
||||
// #ifdef MP-ALIPAY
|
||||
// 支付宝:用权限指引弹窗引导用户开启定位(showAuthGuide 在权限被拒后更可靠)
|
||||
// 说明:调用后系统会弹出引导/授权界面;用户授权成功后再尝试获取定位。
|
||||
try {
|
||||
if (typeof my !== 'undefined' && my.showAuthGuide) {
|
||||
await new Promise((resolve) => {
|
||||
my.showAuthGuide({
|
||||
authType: 'LBS',
|
||||
success: () => resolve(true),
|
||||
fail: () => resolve(false)
|
||||
})
|
||||
})
|
||||
} else if (typeof my !== 'undefined' && my.authorize) {
|
||||
// 兜底:如果 showAuthGuide 不可用,再尝试 authorize 触发授权
|
||||
await new Promise((resolve) => {
|
||||
my.authorize({
|
||||
scope: 'scope.userLocation',
|
||||
success: () => resolve(true),
|
||||
fail: () => resolve(false)
|
||||
})
|
||||
})
|
||||
}
|
||||
} catch (_) {}
|
||||
// #endif
|
||||
|
||||
// 重新触发定位授权/获取流程
|
||||
await getUserLocationAndAddress()
|
||||
await loadPositions()
|
||||
|
||||
// 成功拿到定位后,再隐藏权限提示
|
||||
locationPermissionDenied.value = false
|
||||
} catch (error) {
|
||||
console.error('开启定位失败:', error)
|
||||
// #ifdef MP-ALIPAY
|
||||
if (isLocationPermissionDenied(error)) {
|
||||
locationPermissionDenied.value = true // 保持在页面上提示,避免出现空白区
|
||||
userLocation.value = null
|
||||
positionList.value = []
|
||||
filteredPositions.value = []
|
||||
}
|
||||
// #endif
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const loadPositions = async () => {
|
||||
try {
|
||||
if (!userLocation.value || !userLocation.value.latitude || !userLocation.value.longitude) {
|
||||
@@ -1118,6 +1202,39 @@
|
||||
await doScan()
|
||||
}
|
||||
|
||||
// 统一提取 deviceNo,兼容 URL、编码文本、纯设备号
|
||||
const extractDeviceNoFromText = (rawText) => {
|
||||
if (!rawText) return ''
|
||||
const text = String(rawText).trim()
|
||||
if (!text) return ''
|
||||
|
||||
const candidates = [text]
|
||||
try {
|
||||
const decoded = decodeURIComponent(text)
|
||||
if (decoded && decoded !== text) {
|
||||
candidates.push(decoded)
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
for (const item of candidates) {
|
||||
const fromQuery =
|
||||
getQueryString(item, 'deviceNo') ||
|
||||
getQueryString(item, 'deviceno')
|
||||
if (fromQuery) {
|
||||
return String(fromQuery).trim()
|
||||
}
|
||||
}
|
||||
|
||||
// 二维码内容本身就是设备号时,直接使用原文
|
||||
for (const item of candidates) {
|
||||
if (!item.includes('=') && !item.includes('&') && !item.includes('?')) {
|
||||
return item
|
||||
}
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
const processScanResult = async (scanResult) => {
|
||||
try {
|
||||
console.log('===== 处理扫码结果 =====');
|
||||
@@ -1126,17 +1243,20 @@
|
||||
console.log('result:', scanResult.result);
|
||||
console.log('path:', scanResult.path);
|
||||
|
||||
let deviceNo;
|
||||
let deviceNo = ''
|
||||
if (scanResult.scanType == 'MANUAL') {
|
||||
deviceNo = scanResult.result;
|
||||
console.log('手动输入模式,设备号:', deviceNo);
|
||||
deviceNo = extractDeviceNoFromText(scanResult.result)
|
||||
console.log('手动输入模式,设备号:', deviceNo)
|
||||
} else if (scanResult.scanType == 'QR_CODE') {
|
||||
// 修复:移除多余的引号
|
||||
deviceNo = getQueryString(scanResult.result, 'deviceNo');
|
||||
console.log('二维码扫描模式,提取设备号:', deviceNo);
|
||||
deviceNo =
|
||||
extractDeviceNoFromText(scanResult.result) ||
|
||||
extractDeviceNoFromText(scanResult.path)
|
||||
console.log('二维码扫描模式,提取设备号:', deviceNo)
|
||||
} else {
|
||||
deviceNo = getQueryString(scanResult.path || scanResult.result, 'deviceNo');
|
||||
console.log('其他模式,提取设备号:', deviceNo);
|
||||
deviceNo =
|
||||
extractDeviceNoFromText(scanResult.path) ||
|
||||
extractDeviceNoFromText(scanResult.result)
|
||||
console.log('其他模式,提取设备号:', deviceNo)
|
||||
}
|
||||
|
||||
console.log('最终设备号:', deviceNo);
|
||||
@@ -1986,6 +2106,54 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* 支付宝:定位权限拒绝后的引导文案 */
|
||||
.location-denied-placeholder {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 180rpx;
|
||||
background: #f6f7fb;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1;
|
||||
padding: 0 40rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.denied-content {
|
||||
width: 100%;
|
||||
background: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
padding: 40rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.denied-text {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.denied-enable-btn {
|
||||
margin-top: 28rpx;
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
background: #3EAB64;
|
||||
border-radius: 44rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.denied-enable-btn-text {
|
||||
font-size: 32rpx;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* 手机号授权弹窗 */
|
||||
.phone-auth-popup {
|
||||
position: fixed;
|
||||
|
||||
+19
-16
@@ -63,7 +63,7 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import { getQueryString } from '../../util/index.js';
|
||||
import { Html5Qrcode } from 'html5-qrcode';
|
||||
import { Html5Qrcode, Html5QrcodeSupportedFormats } from 'html5-qrcode';
|
||||
|
||||
const inputPopup = ref(null);
|
||||
const manualDeviceNo = ref('');
|
||||
@@ -75,6 +75,21 @@ const flashOn = ref(false);
|
||||
let html5QrCode = null;
|
||||
let isProcessing = false; // 防止重复处理
|
||||
|
||||
// 统一扫描配置:增大识别区域,提升低清晰度二维码识别成功率
|
||||
const getScanConfig = () => ({
|
||||
fps: 12,
|
||||
qrbox: (viewfinderWidth, viewfinderHeight) => {
|
||||
const minEdge = Math.min(viewfinderWidth, viewfinderHeight);
|
||||
const size = Math.max(220, Math.floor(minEdge * 0.72));
|
||||
return { width: size, height: size };
|
||||
},
|
||||
disableFlip: false,
|
||||
formatsToSupport: [Html5QrcodeSupportedFormats.QR_CODE],
|
||||
experimentalFeatures: {
|
||||
useBarCodeDetectorIfSupported: true
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化扫码
|
||||
const initScan = async () => {
|
||||
try {
|
||||
@@ -124,11 +139,7 @@ const startScanning = async () => {
|
||||
console.log('html5QrCode.start 方法:', typeof html5QrCode.start);
|
||||
|
||||
// 配置扫描参数
|
||||
const config = {
|
||||
fps: 10, // 每秒10帧
|
||||
qrbox: 250, // 扫描框大小(正方形)
|
||||
disableFlip: false
|
||||
};
|
||||
const config = getScanConfig();
|
||||
|
||||
console.log('扫描配置:', config);
|
||||
console.log('准备调用 html5QrCode.start()...');
|
||||
@@ -163,11 +174,7 @@ const startScanning = async () => {
|
||||
// 尝试使用前置摄像头
|
||||
console.log('尝试使用前置摄像头...');
|
||||
try {
|
||||
const config = {
|
||||
fps: 10,
|
||||
qrbox: 250,
|
||||
disableFlip: false
|
||||
};
|
||||
const config = getScanConfig();
|
||||
|
||||
await html5QrCode.start(
|
||||
{ facingMode: "user" },
|
||||
@@ -190,11 +197,7 @@ const startScanning = async () => {
|
||||
// 最后尝试:不指定摄像头
|
||||
console.log('最后尝试:使用默认摄像头...');
|
||||
try {
|
||||
const config = {
|
||||
fps: 10,
|
||||
qrbox: 250,
|
||||
disableFlip: false
|
||||
};
|
||||
const config = getScanConfig();
|
||||
|
||||
// 获取摄像头列表
|
||||
const cameras = await Html5Qrcode.getCameras();
|
||||
|
||||
Reference in New Issue
Block a user