fix:对接高德地图,修复地图bug
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
wxLogin,
|
alipayLogin,
|
||||||
getUserInfo
|
getUserInfo
|
||||||
} from './util/index'
|
} from './util/index'
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
// 保留方法但不调用
|
// 保留方法但不调用
|
||||||
async autoLogin() {
|
async autoLogin() {
|
||||||
try {
|
try {
|
||||||
const loginResult = await wxLogin()
|
const loginResult = await alipayLogin()
|
||||||
// await getUserInfo()
|
// await getUserInfo()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('自动登录失败:', error)
|
console.error('自动登录失败:', error)
|
||||||
|
|||||||
+78
-74
@@ -2,10 +2,20 @@
|
|||||||
<view class="map-container" :class="{ 'full-width': props.fullWidth }" :style="{ '--map-height': props.customHeight || '78vh' }">
|
<view class="map-container" :class="{ 'full-width': props.fullWidth }" :style="{ '--map-height': props.customHeight || '78vh' }">
|
||||||
<!-- 地图容器 -->
|
<!-- 地图容器 -->
|
||||||
<view class="map-wrapper">
|
<view class="map-wrapper">
|
||||||
<!-- 使用小程序原生地图组件 -->
|
<!-- 支付宝小程序地图组件:使用高德地图 -->
|
||||||
<map id="map" class="native-map" :longitude="mapCenter.longitude" :latitude="mapCenter.latitude"
|
<map id="map" class="native-map"
|
||||||
:markers="mapMarkers" :scale="mapZoom" :show-location="false" @regionchange="onMapRegionChange"
|
:longitude="mapCenter.longitude"
|
||||||
@markertap="onMapMarkerTap" @callouttap="onCalloutTap" @updated="onMapUpdated" @error="onMapError">
|
:latitude="mapCenter.latitude"
|
||||||
|
:markers="mapMarkers"
|
||||||
|
:scale="mapZoom"
|
||||||
|
:show-location="false"
|
||||||
|
@regionchange="onMapRegionChange"
|
||||||
|
@markertap="onMapMarkerTap"
|
||||||
|
@tap="onMapTap"
|
||||||
|
@updated="onMapUpdated"
|
||||||
|
@error="onMapError">
|
||||||
|
</map>
|
||||||
|
|
||||||
<!-- 覆盖在地图上的广告轮播(使用 cover-view 以兼容小程序原生组件层级) -->
|
<!-- 覆盖在地图上的广告轮播(使用 cover-view 以兼容小程序原生组件层级) -->
|
||||||
<cover-view class="index-swiper" v-if="!props.hideControls && !props.hideMapOverlays && currentBannerImage">
|
<cover-view class="index-swiper" v-if="!props.hideControls && !props.hideMapOverlays && currentBannerImage">
|
||||||
<cover-image :src="currentBannerImage" class="index-swiper-img" mode="aspectFill" @tap="handleBannerTap"></cover-image>
|
<cover-image :src="currentBannerImage" class="index-swiper-img" mode="aspectFill" @tap="handleBannerTap"></cover-image>
|
||||||
@@ -20,24 +30,23 @@
|
|||||||
</cover-view>
|
</cover-view>
|
||||||
</cover-view>
|
</cover-view>
|
||||||
|
|
||||||
<!-- 地图中心固定定位图标 -->
|
<!-- 地图中心固定定位图标 -->
|
||||||
<cover-view class="center-location-marker" v-if="!props.hideMapOverlays">
|
<cover-view class="center-location-marker" v-if="!props.hideMapOverlays">
|
||||||
<cover-image src="/static/location-icon.png" class="center-marker-icon"></cover-image>
|
<cover-image src="/static/location-icon.png" class="center-marker-icon"></cover-image>
|
||||||
</cover-view>
|
</cover-view>
|
||||||
|
|
||||||
<cover-view class="map-side-controls" v-if="!props.hideControls && !props.hideMapOverlays">
|
<!-- 地图侧边控制按钮:重定位、客服中心、查看附近设备 -->
|
||||||
<cover-view class="side-btn locate" @tap="handleRelocate">
|
<cover-view class="map-side-controls" v-if="!props.hideControls && !props.hideMapOverlays">
|
||||||
<cover-image class="side-icon" src="/static/location.png"></cover-image>
|
<cover-view class="side-btn locate" @tap="handleRelocate">
|
||||||
</cover-view>
|
<cover-image class="side-icon" src="/static/location.png"></cover-image>
|
||||||
<cover-view class="side-btn service" @tap="handleService">
|
|
||||||
<cover-image class="side-icon" src="/static/customer-service.png"></cover-image>
|
|
||||||
</cover-view>
|
|
||||||
<cover-view class="side-btn search" @tap="handleSearch">
|
|
||||||
<cover-image class="side-icon" src="/static/other_device.png"></cover-image>
|
|
||||||
</cover-view>
|
|
||||||
|
|
||||||
</cover-view>
|
</cover-view>
|
||||||
</map>
|
<cover-view class="side-btn service" @tap="handleService">
|
||||||
|
<cover-image class="side-icon" src="/static/customer-service.png"></cover-image>
|
||||||
|
</cover-view>
|
||||||
|
<cover-view class="side-btn search" @tap="handleSearch">
|
||||||
|
<cover-image class="side-icon" src="/static/other_device.png"></cover-image>
|
||||||
|
</cover-view>
|
||||||
|
</cover-view>
|
||||||
|
|
||||||
<!-- 地图加载状态 -->
|
<!-- 地图加载状态 -->
|
||||||
<view class="map-loading" v-if="isLoading">
|
<view class="map-loading" v-if="isLoading">
|
||||||
@@ -245,6 +254,35 @@
|
|||||||
deep: true
|
deep: true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 启动广告轮播
|
||||||
|
const startBannerRotation = () => {
|
||||||
|
// 如果只有一张或没有图片,不需要轮播
|
||||||
|
if (!props.bannerImages || props.bannerImages.length <= 1) {
|
||||||
|
console.log('图片数量不足,不启动轮播')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清除旧的定时器
|
||||||
|
stopBannerRotation()
|
||||||
|
|
||||||
|
console.log('开始广告轮播定时器')
|
||||||
|
// 每3秒切换一次
|
||||||
|
bannerTimer = setInterval(() => {
|
||||||
|
const nextIndex = (currentBannerIndex.value + 1) % props.bannerImages.length
|
||||||
|
console.log('轮播切换:', currentBannerIndex.value, '->', nextIndex)
|
||||||
|
currentBannerIndex.value = nextIndex
|
||||||
|
}, 3000)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 停止广告轮播
|
||||||
|
const stopBannerRotation = () => {
|
||||||
|
if (bannerTimer) {
|
||||||
|
console.log('停止广告轮播')
|
||||||
|
clearInterval(bannerTimer)
|
||||||
|
bannerTimer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 监听广告图片变化,启动或停止轮播
|
// 监听广告图片变化,启动或停止轮播
|
||||||
watch(() => props.bannerImages, (newImages, oldImages) => {
|
watch(() => props.bannerImages, (newImages, oldImages) => {
|
||||||
console.log('广告图片变化:', newImages?.length, '张')
|
console.log('广告图片变化:', newImages?.length, '张')
|
||||||
@@ -270,25 +308,22 @@
|
|||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 地图区域变化事件(带防抖优化)
|
// 地图区域变化事件(支付宝小程序,带防抖优化)
|
||||||
const onMapRegionChange = (e) => {
|
const onMapRegionChange = (e) => {
|
||||||
|
if (!e) {
|
||||||
// 只处理结束事件
|
|
||||||
if (!e || e.type !== 'end') {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const causedBy = e.causedBy || e.detail?.causedBy
|
// 获取触发原因和中心位置
|
||||||
|
const causedBy = e.detail?.causedBy || e.causedBy
|
||||||
|
const centerLocation = e.detail?.centerLocation || e.centerLocation || e.detail?.location
|
||||||
|
|
||||||
if (causedBy === 'gesture' || causedBy === 'scale' || causedBy === 'drag'||causedBy==='update') {
|
if (causedBy === 'gesture' || causedBy === 'scale' || causedBy === 'drag' || causedBy === 'update') {
|
||||||
// 清除之前的定时器
|
// 清除之前的定时器
|
||||||
if (regionChangeTimer) {
|
if (regionChangeTimer) {
|
||||||
clearTimeout(regionChangeTimer)
|
clearTimeout(regionChangeTimer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 直接从事件对象中获取最新的中心点位置
|
|
||||||
const centerLocation = e.detail?.centerLocation || e.centerLocation
|
|
||||||
|
|
||||||
if (centerLocation && centerLocation.longitude && centerLocation.latitude) {
|
if (centerLocation && centerLocation.longitude && centerLocation.latitude) {
|
||||||
// 防抖:500ms后执行查询
|
// 防抖:500ms后执行查询
|
||||||
regionChangeTimer = setTimeout(() => {
|
regionChangeTimer = setTimeout(() => {
|
||||||
@@ -298,13 +333,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
mapCenter.value = newCenter;
|
mapCenter.value = newCenter;
|
||||||
|
|
||||||
|
|
||||||
// 触发父组件查询新位置的场地
|
// 触发父组件查询新位置的场地
|
||||||
emit('mapCenterChange', newCenter)
|
emit('mapCenterChange', newCenter)
|
||||||
}, 500)
|
}, 500)
|
||||||
} else {
|
} else {
|
||||||
// 兜底方案:如果事件中没有centerLocation,才使用API获取
|
// 兜底方案:使用API获取地图中心
|
||||||
regionChangeTimer = setTimeout(() => {
|
regionChangeTimer = setTimeout(() => {
|
||||||
if (mapContext.value) {
|
if (mapContext.value) {
|
||||||
mapContext.value.getCenterLocation({
|
mapContext.value.getCenterLocation({
|
||||||
@@ -325,15 +358,20 @@
|
|||||||
}
|
}
|
||||||
}, 500)
|
}, 500)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 标记点点击事件
|
// 标记点点击事件(支付宝小程序)
|
||||||
const onMapMarkerTap = (e) => {
|
const onMapMarkerTap = (e) => {
|
||||||
const markerId = e.detail?.markerId || e.markerId
|
if (!e) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取markerId
|
||||||
|
const markerId = e.detail?.markerId || e.markerId || e.detail?.marker?.id
|
||||||
|
|
||||||
// 查找对应的场地位置信息
|
// 查找对应的场地位置信息
|
||||||
if (props.filteredPositions && props.filteredPositions.length > 0) {
|
if (props.filteredPositions && props.filteredPositions.length > 0 && markerId) {
|
||||||
const position = props.filteredPositions[markerId - 1]
|
const position = props.filteredPositions[markerId - 1]
|
||||||
if (position) {
|
if (position) {
|
||||||
emit('markerTap', position)
|
emit('markerTap', position)
|
||||||
@@ -341,14 +379,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 标记点气泡点击事件
|
// 地图点击事件(支付宝小程序)
|
||||||
const onCalloutTap = (e) => {
|
const onMapTap = (e) => {
|
||||||
const markerId = e.markerId
|
console.log('地图点击事件:', e)
|
||||||
const marker = mapMarkers.value.find(item => item.id === markerId)
|
|
||||||
|
|
||||||
if (marker && marker.position) {
|
|
||||||
emit('markerTap', marker.position)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 地图错误事件
|
// 地图错误事件
|
||||||
@@ -391,35 +424,6 @@ const handleSearch = () => {
|
|||||||
handleJoinTap()
|
handleJoinTap()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 启动广告轮播
|
|
||||||
const startBannerRotation = () => {
|
|
||||||
// 如果只有一张或没有图片,不需要轮播
|
|
||||||
if (!props.bannerImages || props.bannerImages.length <= 1) {
|
|
||||||
console.log('图片数量不足,不启动轮播')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清除旧的定时器
|
|
||||||
stopBannerRotation()
|
|
||||||
|
|
||||||
console.log('开始广告轮播定时器')
|
|
||||||
// 每3秒切换一次
|
|
||||||
bannerTimer = setInterval(() => {
|
|
||||||
const nextIndex = (currentBannerIndex.value + 1) % props.bannerImages.length
|
|
||||||
console.log('轮播切换:', currentBannerIndex.value, '->', nextIndex)
|
|
||||||
currentBannerIndex.value = nextIndex
|
|
||||||
}, 3000)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 停止广告轮播
|
|
||||||
const stopBannerRotation = () => {
|
|
||||||
if (bannerTimer) {
|
|
||||||
console.log('停止广告轮播')
|
|
||||||
clearInterval(bannerTimer)
|
|
||||||
bannerTimer = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleScan = () => {
|
const handleScan = () => {
|
||||||
emit('scan')
|
emit('scan')
|
||||||
}
|
}
|
||||||
@@ -595,7 +599,7 @@ const handleSearch = () => {
|
|||||||
// min-width: 160rpx;
|
// min-width: 160rpx;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
// height: 72rpx;
|
// height: 72rpx;
|
||||||
background: rgba(255, 255, 255, 0.96);
|
// background: rgba(255, 255, 255, 0.96);
|
||||||
border-radius: 36rpx;
|
border-radius: 36rpx;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|||||||
@@ -107,7 +107,7 @@
|
|||||||
|
|
||||||
const emit = defineEmits(['pay', 'cancel', 'return-device', 'details']);
|
const emit = defineEmits(['pay', 'cancel', 'return-device', 'details']);
|
||||||
|
|
||||||
const rawStatus = computed(() => props.order.orderStatus ?? props.order.status);
|
const rawStatus = computed(() => props.order.orderStatus != null ? props.order.orderStatus : props.order.status);
|
||||||
const normalizedStatus = computed(() => {
|
const normalizedStatus = computed(() => {
|
||||||
const s = rawStatus.value;
|
const s = rawStatus.value;
|
||||||
switch (s) {
|
switch (s) {
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ const request = (option) => {
|
|||||||
"Content-Type": option.headers && option.headers["Content-Type"] ? option.headers["Content-Type"] : (option.method && option.method.toUpperCase() === 'POST' ? 'application/json' : 'application/x-www-form-urlencoded'),
|
"Content-Type": option.headers && option.headers["Content-Type"] ? option.headers["Content-Type"] : (option.method && option.method.toUpperCase() === 'POST' ? 'application/json' : 'application/x-www-form-urlencoded'),
|
||||||
...option.headers,
|
...option.headers,
|
||||||
'appid': appid,
|
'appid': appid,
|
||||||
|
'platform': 'alipay', // 标识支付宝小程序平台
|
||||||
'Authorization': "Bearer " + uni.getStorageSync('token'),
|
'Authorization': "Bearer " + uni.getStorageSync('token'),
|
||||||
'Clientid': uni.getStorageSync('client_id')
|
'Clientid': uni.getStorageSync('client_id')
|
||||||
},
|
},
|
||||||
|
|||||||
+4
-4
@@ -1,8 +1,8 @@
|
|||||||
// export const URL = "https://my.gxfs123.com/api" //正式服务器-弃用
|
// export const URL = "https://my.gxfs123.com/api" //正式服务器-弃用
|
||||||
// export const URL = "https://manager.fdzpower.com/api" //正式服务器
|
export const URL = "https://manager.fdzpower.com/api" //正式服务器
|
||||||
export const URL = "https://fansdev.gxfs123.com/api" //测试服务器
|
// export const URL = "https://fansdev.gxfs123.com/api" //测试服务器
|
||||||
// export const URL = "http://192.168.5.30:8080" //本地调试
|
// export const URL = "http://192.168.5.30:8080" //本地调试
|
||||||
// export const URL = "http://127.0.0.1:8080" //本地调试
|
// export const URL = "http://127.0.0.1:8080" //本地调试
|
||||||
|
|
||||||
export const appid = "wx2165f0be356ae7a9" //微信小程序appid
|
export const appid = "2021006117693332" //支付宝小程序appid
|
||||||
export const ZFBappid = "2021006117693332" //支付宝小程序appid
|
export const ZFBappid = "2021006117693332" //支付宝小程序appid(保留兼容)
|
||||||
+7
-2
@@ -60,7 +60,7 @@ export default {
|
|||||||
orders: '订单',
|
orders: '订单',
|
||||||
settings: '设置',
|
settings: '设置',
|
||||||
back: '返回',
|
back: '返回',
|
||||||
title: '风电者共享风扇&暖手充电宝'
|
title: '风电者共享风扇&暖手宝'
|
||||||
},
|
},
|
||||||
|
|
||||||
app: {
|
app: {
|
||||||
@@ -71,7 +71,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
home: {
|
home: {
|
||||||
title: '风电者共享风扇&暖手充电宝',
|
title: '风电者共享风扇&暖手宝',
|
||||||
nearbyDevices: '附近设备',
|
nearbyDevices: '附近设备',
|
||||||
scanToUse: '扫码使用',
|
scanToUse: '扫码使用',
|
||||||
personalCenter: '个人中心',
|
personalCenter: '个人中心',
|
||||||
@@ -135,6 +135,7 @@ export default {
|
|||||||
useInDesignatedArea: '请在指定区域内使用设备',
|
useInDesignatedArea: '请在指定区域内使用设备',
|
||||||
rentDepositFree: '免押金租借',
|
rentDepositFree: '免押金租借',
|
||||||
wxPayScoreDesc: '微信支付分 | 550分以上优享',
|
wxPayScoreDesc: '微信支付分 | 550分以上优享',
|
||||||
|
alipayScoreDesc: '支付宝信用免押 | 550分以上优享',
|
||||||
checking: '检查中',
|
checking: '检查中',
|
||||||
deviceNoNotRecognized: '未识别到设备编号',
|
deviceNoNotRecognized: '未识别到设备编号',
|
||||||
processFailed: '处理失败,请稍后重试',
|
processFailed: '处理失败,请稍后重试',
|
||||||
@@ -191,10 +192,12 @@ export default {
|
|||||||
confirmCancel: '确认取消订单?',
|
confirmCancel: '确认取消订单?',
|
||||||
confirmReturn: '确认归还设备?',
|
confirmReturn: '确认归还设备?',
|
||||||
wxPayScore: '微信支付分',
|
wxPayScore: '微信支付分',
|
||||||
|
alipayScore: '支付宝信用免押',
|
||||||
depositFree: '免押租借',
|
depositFree: '免押租借',
|
||||||
whitelistOrder: '白名单订单',
|
whitelistOrder: '白名单订单',
|
||||||
memberOrder: '会员订单',
|
memberOrder: '会员订单',
|
||||||
wxPay: '微信支付',
|
wxPay: '微信支付',
|
||||||
|
alipayPay: '支付宝支付',
|
||||||
depositPay: '押金租借',
|
depositPay: '押金租借',
|
||||||
paymentInProgress: '支付中',
|
paymentInProgress: '支付中',
|
||||||
paymentFailedRetry: '支付失败,请重新支付',
|
paymentFailedRetry: '支付失败,请重新支付',
|
||||||
@@ -291,6 +294,7 @@ export default {
|
|||||||
getUserInfoSuccess: '获取用户信息成功',
|
getUserInfoSuccess: '获取用户信息成功',
|
||||||
getUserInfoFailed: '获取用户信息失败',
|
getUserInfoFailed: '获取用户信息失败',
|
||||||
pleaseUseInWechat: '请在微信小程序中使用此功能',
|
pleaseUseInWechat: '请在微信小程序中使用此功能',
|
||||||
|
pleaseUseInAlipay: '请在支付宝小程序中使用此功能',
|
||||||
agreeToTerms: '我已阅读并同意',
|
agreeToTerms: '我已阅读并同意',
|
||||||
pleaseAgreeToTerms: '请先阅读并同意《用户协议》和《隐私政策》',
|
pleaseAgreeToTerms: '请先阅读并同意《用户协议》和《隐私政策》',
|
||||||
loginSuccess: '登录成功',
|
loginSuccess: '登录成功',
|
||||||
@@ -319,6 +323,7 @@ export default {
|
|||||||
paymentAmount: '支付金额',
|
paymentAmount: '支付金额',
|
||||||
paymentMethod: '支付方式',
|
paymentMethod: '支付方式',
|
||||||
wechatPay: '微信支付',
|
wechatPay: '微信支付',
|
||||||
|
alipayPay: '支付宝支付',
|
||||||
alipay: '支付宝',
|
alipay: '支付宝',
|
||||||
balance: '余额支付',
|
balance: '余额支付',
|
||||||
payNow: '立即支付',
|
payNow: '立即支付',
|
||||||
|
|||||||
+9
-19
@@ -43,36 +43,26 @@
|
|||||||
"ios" : {},
|
"ios" : {},
|
||||||
"sdkConfigs" : {
|
"sdkConfigs" : {
|
||||||
"maps" : {
|
"maps" : {
|
||||||
"amap" : {
|
"qqmap" : {
|
||||||
"appkey_ios" : "4c513a688938fd89b88b296e867f66ec",
|
"appkey_ios" : "RO5BZ-ECZ63-7US3C-RT5QW-TIDZE-2FF35",
|
||||||
"appkey_android" : "4c513a688938fd89b88b296e867f66ec"
|
"appkey_android" : "RO5BZ-ECZ63-7US3C-RT5QW-TIDZE-2FF35"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"quickapp" : {},
|
"quickapp" : {},
|
||||||
"mp-weixin" : {
|
|
||||||
"appid" : "wx2165f0be356ae7a9",
|
|
||||||
"setting" : {
|
|
||||||
"urlCheck" : false
|
|
||||||
},
|
|
||||||
"usingComponents" : true,
|
|
||||||
"permission" : {
|
|
||||||
"scope.getPhoneNumber" : {
|
|
||||||
"desc" : "您的手机号将用于登录和订单服务"
|
|
||||||
},
|
|
||||||
"scope.userLocation" : {
|
|
||||||
"desc" : "您的位置信息将用于获取附近的设备"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"requiredPrivateInfos" : [ "getLocation", "chooseLocation" ]
|
|
||||||
},
|
|
||||||
"mp-alipay" : {
|
"mp-alipay" : {
|
||||||
|
"component2": true,
|
||||||
"usingComponents" : true,
|
"usingComponents" : true,
|
||||||
"appid" : "2021006117693332",
|
"appid" : "2021006117693332",
|
||||||
"unipush" : {
|
"unipush" : {
|
||||||
"enable" : false
|
"enable" : false
|
||||||
|
},
|
||||||
|
"permission" : {
|
||||||
|
"scope.userLocation" : {
|
||||||
|
"desc" : "您的位置信息将用于获取附近的设备"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mp-baidu" : {
|
"mp-baidu" : {
|
||||||
|
|||||||
+20
-45
@@ -72,12 +72,12 @@
|
|||||||
<!-- 底部操作区 -->
|
<!-- 底部操作区 -->
|
||||||
<view class="footer">
|
<view class="footer">
|
||||||
<button class="rent-button" :class="{ 'return-button': hasActiveOrder }"
|
<button class="rent-button" :class="{ 'return-button': hasActiveOrder }"
|
||||||
@click="handleRent('wx-score-pay')">
|
@click="handleRent('alipay-score-pay')">
|
||||||
<text>{{ hasActiveOrder ? $t('order.returnDevice') : $t('device.rentDepositFree') }}</text>
|
<text>{{ hasActiveOrder ? $t('order.returnDevice') : $t('device.rentDepositFree') }}</text>
|
||||||
</button>
|
</button>
|
||||||
<view class="wechat-credit">
|
<view class="alipay-credit">
|
||||||
<image src="/static/images/wxpayflag.png" mode="aspectFit" class="wx-icon"></image>
|
<image src="/static/images/alipay.svg" mode="aspectFit" class="alipay-icon"></image>
|
||||||
<text class="credit-text">{{ $t('device.wxPayScoreDesc') }}</text>
|
<text class="credit-text">{{ $t('device.alipayScoreDesc') }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@
|
|||||||
cancelOrder
|
cancelOrder
|
||||||
} from '@/config/api/order.js'
|
} from '@/config/api/order.js'
|
||||||
import {
|
import {
|
||||||
initiateWeChatScorePayment,
|
initiateAlipayPayment,
|
||||||
getUserInfo,
|
getUserInfo,
|
||||||
getUserPhoneNumber
|
getUserPhoneNumber
|
||||||
} from '@/util/index.js'
|
} from '@/util/index.js'
|
||||||
@@ -466,32 +466,8 @@
|
|||||||
uni.showLoading({
|
uni.showLoading({
|
||||||
title: $t('common.processing')
|
title: $t('common.processing')
|
||||||
})
|
})
|
||||||
// --- 第一步:先请求订阅消息(必须在用户点击的同步上下文中)---
|
// --- 支付宝小程序不需要订阅消息,移除相关代码 ---
|
||||||
if (payWay === 'wx-score-pay') {
|
// 支付宝小程序使用消息推送,不需要订阅消息
|
||||||
console.log('准备请求订阅消息(在异步操作之前),时间:', new Date().toLocaleTimeString());
|
|
||||||
try {
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
uni.requestSubscribeMessage({
|
|
||||||
tmplIds: ['o7OMTIcHnFBR7mvsggxFtdt8FfIgSl-v0swVUefGx6w'],
|
|
||||||
success: (subscribeRes) => {
|
|
||||||
console.log('订阅消息success回调,时间:', new Date()
|
|
||||||
.toLocaleTimeString(), subscribeRes);
|
|
||||||
resolve(subscribeRes);
|
|
||||||
},
|
|
||||||
fail: (subscribeErr) => {
|
|
||||||
console.log('订阅消息fail回调,时间:', new Date().toLocaleTimeString(),
|
|
||||||
subscribeErr);
|
|
||||||
// 订阅失败不影响主流程
|
|
||||||
resolve(subscribeErr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
console.log('订阅消息完成,时间:', new Date().toLocaleTimeString());
|
|
||||||
} catch (subscribeError) {
|
|
||||||
console.log('订阅消息异常', subscribeError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// --- 订阅消息请求完成 ---
|
|
||||||
|
|
||||||
console.log(deviceId.value);
|
console.log(deviceId.value);
|
||||||
// 调用设备租借接口
|
// 调用设备租借接口
|
||||||
@@ -504,7 +480,7 @@
|
|||||||
const order = rentResult.data
|
const order = rentResult.data
|
||||||
console.log('订单信息', order);
|
console.log('订单信息', order);
|
||||||
|
|
||||||
if (payWay == 'wx-pay') {
|
if (payWay == 'alipay-pay' || payWay == 'wx-pay') {
|
||||||
// 当支付方式为押金支付时
|
// 当支付方式为押金支付时
|
||||||
uni.hideLoading()
|
uni.hideLoading()
|
||||||
const res = await getOrderByOrderNo(order.orderNo);
|
const res = await getOrderByOrderNo(order.orderNo);
|
||||||
@@ -519,29 +495,28 @@
|
|||||||
url: `/pages/order/payment?orderId=${order.orderId}&packagePrice=${packagePrice}&totalAmount=${totalAmount}&depositAmount=${deposit}${deviceInfo.value && deviceInfo.value.feeConfig ? '&feeConfig=' + encodeURIComponent(deviceInfo.value.feeConfig) : ''}`
|
url: `/pages/order/payment?orderId=${order.orderId}&packagePrice=${packagePrice}&totalAmount=${totalAmount}&depositAmount=${deposit}${deviceInfo.value && deviceInfo.value.feeConfig ? '&feeConfig=' + encodeURIComponent(deviceInfo.value.feeConfig) : ''}`
|
||||||
})
|
})
|
||||||
|
|
||||||
} else if (payWay == 'wx-score-pay') {
|
} else if (payWay == 'alipay-score-pay' || payWay == 'wx-score-pay') {
|
||||||
// 当支付方式为支付分支付时
|
// 当支付方式为支付宝信用免押支付时
|
||||||
uni.hideLoading()
|
uni.hideLoading()
|
||||||
// 获取支付分所需参数
|
// 获取支付宝信用免押所需参数
|
||||||
const res = await getOrderByOrderNoScore(order.orderNo);
|
const res = await getOrderByOrderNoScore(order.orderNo);
|
||||||
uni.hideLoading()
|
uni.hideLoading()
|
||||||
|
|
||||||
if (res && res.code === 200) {
|
if (res && res.code === 200) {
|
||||||
try {
|
try {
|
||||||
// 调用微信支付分小程序
|
// 调用支付宝信用免押小程序
|
||||||
const payResult = await initiateWeChatScorePayment(res);
|
const payResult = await initiateAlipayPayment(res);
|
||||||
console.log('支付分调用结果', payResult);
|
console.log('支付宝信用免押调用结果', payResult);
|
||||||
// 成功则跳转到等待页面
|
// 成功则跳转到等待页面
|
||||||
if (payResult.errCode == '0' && payResult.extraData && Object.keys(payResult.extraData)
|
if (payResult && payResult.success !== false) {
|
||||||
.length > 0) {
|
console.log('支付宝信用免押授权成功,准备跳转到等待页,时间:', new Date().toLocaleTimeString());
|
||||||
console.log('支付分授权成功,准备跳转到等待页,时间:', new Date().toLocaleTimeString());
|
// 跳转到等待页面
|
||||||
// 跳转到等待页面(订阅消息已经在前面完成了)
|
|
||||||
uni.redirectTo({
|
uni.redirectTo({
|
||||||
url: `/pages/waiting/index?orderNo=${order.orderNo}&orderId=${order.orderId}&deviceId=${deviceId.value}`
|
url: `/pages/waiting/index?orderNo=${order.orderNo}&orderId=${order.orderId}&deviceId=${deviceId.value}`
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
console.log('支付分未完成授权或用户取消,extraData:', payResult.extraData);
|
console.log('支付宝信用免押未完成授权或用户取消:', payResult);
|
||||||
// 用户取消授权,需要取消订单
|
// 用户取消授权,需要取消订单
|
||||||
try {
|
try {
|
||||||
uni.showLoading({
|
uni.showLoading({
|
||||||
@@ -876,13 +851,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wechat-credit {
|
.alipay-credit {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-top: 16rpx;
|
margin-top: 16rpx;
|
||||||
|
|
||||||
.wx-icon {
|
.alipay-icon {
|
||||||
width: 48rpx;
|
width: 48rpx;
|
||||||
height: 38rpx;
|
height: 38rpx;
|
||||||
margin-right: 8rpx;
|
margin-right: 8rpx;
|
||||||
|
|||||||
@@ -306,7 +306,7 @@
|
|||||||
// 获取图片列表(支持字符串或数组)
|
// 获取图片列表(支持字符串或数组)
|
||||||
const getImageList = (item) => {
|
const getImageList = (item) => {
|
||||||
if (!item) return [];
|
if (!item) return [];
|
||||||
const pictureSource = item.pictureUrls ?? item.picturePath;
|
const pictureSource = item.pictureUrls != null ? item.pictureUrls : item.picturePath;
|
||||||
if (!pictureSource) return [];
|
if (!pictureSource) return [];
|
||||||
if (Array.isArray(pictureSource)) {
|
if (Array.isArray(pictureSource)) {
|
||||||
return pictureSource.filter(img => !!img);
|
return pictureSource.filter(img => !!img);
|
||||||
|
|||||||
+112
-107
@@ -1,30 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="container fullscreen">
|
<view class="container fullscreen">
|
||||||
<!-- 自定义导航栏 -->
|
<!-- 自定义导航栏 -->
|
||||||
<view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
|
<view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'rpx' }">
|
||||||
<view class="navbar-content" :style="{ height: navBarHeight + 'px' }">
|
<view class="navbar-content" :style="{ height: navBarHeight + 'rpx' }">
|
||||||
<text class="navbar-title">{{ $t('home.title') }}</text>
|
<text class="navbar-title">{{ $t('home.title') }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 顶部信息区域(通知、招商等) -->
|
<!-- 顶部信息区域(通知、招商等) -->
|
||||||
<view class="top-info-section" :style="{ top: (statusBarHeight + navBarHeight) + 'px' }">
|
<view class="top-info-section" :style="{ top: (statusBarHeight + navBarHeight) + 'rpx' }">
|
||||||
<!-- 通知栏 -->
|
<!-- 通知栏 -->
|
||||||
<view class="notice-wrapper" v-if="noticeText" @click="openNoticePopup">
|
<view class="notice-wrapper" v-if="noticeText" @click="openNoticePopup">
|
||||||
<uv-notice-bar :text="noticeText" :speed="50" :show-icon="true" color="#07c160" bg-color="#E8F8EF"
|
<uv-notice-bar :text="noticeText" :speed="50" :show-icon="true" color="#07c160" bg-color="#E8F8EF"
|
||||||
icon="volume"></uv-notice-bar>
|
icon="volume"></uv-notice-bar>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 内容区域 -->
|
<!-- 内容区域 -->
|
||||||
<view class="main-content" :style="{ paddingTop: (statusBarHeight + navBarHeight + noticeHeight) + 'px' }">
|
<view class="main-content"
|
||||||
<!-- 全屏地图组件 -->
|
:style="{ paddingTop: (statusBarHeight + navBarHeight+navBarHeight + noticeHeight) + 'rpx' }">
|
||||||
<MapComponent v-if="!isLoading && userLocation" ref="mapRef" :userLocation="userLocation"
|
<!-- 全屏地图组件 -->
|
||||||
:positionList="positionList" :filteredPositions="filteredPositions" :searchKeyword="searchKeyword"
|
<MapComponent v-if="!isLoading && userLocation" ref="mapRef" :userLocation="userLocation"
|
||||||
:enableMarkers="true" :bannerImages="bannerImages"
|
:positionList="positionList" :filteredPositions="filteredPositions" :searchKeyword="searchKeyword"
|
||||||
:hideMapOverlays="showGuidePopup || showNoticePopup || showActivityPopup"
|
:enableMarkers="true" :bannerImages="bannerImages"
|
||||||
@relocate="handleRelocate" @scan="handleScan" @showList="showLocationList" @markerTap="selectPosition"
|
:hideMapOverlays="showGuidePopup || showNoticePopup || showActivityPopup" @relocate="handleRelocate"
|
||||||
@mapCenterChange="onMapCenterChange" @bannerClick="handleBannerClick" />
|
@scan="handleScan" @showList="showLocationList" @markerTap="selectPosition"
|
||||||
|
@mapCenterChange="onMapCenterChange" @bannerClick="handleBannerClick" />
|
||||||
|
|
||||||
<!-- 地图加载状态 -->
|
<!-- 地图加载状态 -->
|
||||||
<view v-if="isLoading || !userLocation" class="map-loading-placeholder">
|
<view v-if="isLoading || !userLocation" class="map-loading-placeholder">
|
||||||
@@ -101,7 +102,7 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 使用指南:居中弹出(ref 控制 open/close) -->
|
<!-- 使用指南:居中弹出(ref 控制 open/close) -->
|
||||||
<uv-popup ref="guidePopup" mode="center" :overlay="true" :closeOnClickOverlay="false"
|
<uv-popup ref="guidePopup" mode="center" :overlay="true" :closeOnClickOverlay="false"
|
||||||
:safeAreaInsetBottom="false">
|
:safeAreaInsetBottom="false">
|
||||||
<view class="guide-popup">
|
<view class="guide-popup">
|
||||||
<view class="guide-header">
|
<view class="guide-header">
|
||||||
@@ -187,7 +188,7 @@
|
|||||||
} from 'vue'
|
} from 'vue'
|
||||||
import {
|
import {
|
||||||
getQueryString,
|
getQueryString,
|
||||||
wxLogin
|
alipayLogin
|
||||||
} from '../../util/index.js'
|
} from '../../util/index.js'
|
||||||
import {
|
import {
|
||||||
URL
|
URL
|
||||||
@@ -218,12 +219,9 @@
|
|||||||
useI18n
|
useI18n
|
||||||
} from '../../utils/i18n.js'
|
} from '../../utils/i18n.js'
|
||||||
|
|
||||||
// 开启右上角分享菜单(仅 mp-weixin 有效)
|
// 支付宝小程序不支持分享菜单,移除相关代码
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-ALIPAY
|
||||||
wx.showShareMenu({
|
// 支付宝小程序分享功能通过页面配置实现
|
||||||
withShareTicket: true,
|
|
||||||
menus: ['shareAppMessage', 'shareTimeline']
|
|
||||||
})
|
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -317,7 +315,7 @@
|
|||||||
'Content-Language': languageCode
|
'Content-Language': languageCode
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
type: 'wx_user_type' // 微信小程序用户端
|
type: 'zfb_user_type' // 支付宝小程序用户端
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -365,8 +363,8 @@
|
|||||||
'Content-Language': languageCode
|
'Content-Language': languageCode
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
appPlatform: 'wechat', // 微信平台
|
appPlatform: 'alipay', // 支付宝平台
|
||||||
appType: 'user' // 用户端
|
appType: 'user' // 用户端
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -394,7 +392,9 @@
|
|||||||
console.log('点击首页广告:', index, bannerImages.value[index])
|
console.log('点击首页广告:', index, bannerImages.value[index])
|
||||||
// 可以根据需要添加跳转逻辑
|
// 可以根据需要添加跳转逻辑
|
||||||
// 例如跳转到合作加盟页面
|
// 例如跳转到合作加盟页面
|
||||||
uni.navigateTo({ url: '/pages/join/index' })
|
uni.navigateTo({
|
||||||
|
url: '/pages/join/index'
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询最近的活动
|
// 查询最近的活动
|
||||||
@@ -480,15 +480,13 @@
|
|||||||
const systemInfo = uni.getSystemInfoSync()
|
const systemInfo = uni.getSystemInfoSync()
|
||||||
statusBarHeight.value = systemInfo.statusBarHeight || 0
|
statusBarHeight.value = systemInfo.statusBarHeight || 0
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-ALIPAY
|
||||||
// 获取胶囊按钮位置信息
|
// 支付宝小程序导航栏高度计算
|
||||||
const menuButtonInfo = uni.getMenuButtonBoundingClientRect()
|
navBarHeight.value = 44
|
||||||
// 计算导航栏内容高度:(胶囊底部坐标 - 状态栏高度) 确保与胶囊对齐
|
|
||||||
navBarHeight.value = (menuButtonInfo.top - systemInfo.statusBarHeight) * 2 + menuButtonInfo.height
|
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifndef MP-WEIXIN
|
// #ifndef MP-ALIPAY
|
||||||
// 非微信小程序使用默认高度
|
// 其他平台使用默认高度
|
||||||
navBarHeight.value = 44
|
navBarHeight.value = 44
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
@@ -523,94 +521,94 @@
|
|||||||
console.warn('清理旧缓存失败:', e);
|
console.warn('清理旧缓存失败:', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开发环境测试距离计算
|
// 开发环境测试距离计算
|
||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
testDistanceCalculation()
|
testDistanceCalculation()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 并行加载公告和广告(不依赖定位)
|
|
||||||
await Promise.all([
|
|
||||||
getNoticeText(),
|
|
||||||
getBannerImages()
|
|
||||||
])
|
|
||||||
|
|
||||||
// 1. 先获取用户位置
|
// 并行加载公告和广告(不依赖定位)
|
||||||
await getUserLocationAndAddress()
|
await Promise.all([
|
||||||
|
getNoticeText(),
|
||||||
|
getBannerImages()
|
||||||
|
])
|
||||||
|
|
||||||
// 2. 加载场地列表(依赖定位)
|
// 1. 先获取用户位置
|
||||||
await loadPositions()
|
await getUserLocationAndAddress()
|
||||||
|
|
||||||
// 3. 查询活动并显示弹窗
|
// 2. 加载场地列表(依赖定位)
|
||||||
await checkActiveActivity()
|
await loadPositions()
|
||||||
|
|
||||||
|
// 3. 查询活动并显示弹窗
|
||||||
|
await checkActiveActivity()
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('初始化失败:', error)
|
console.error('初始化失败:', error)
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: $t('home.getLocationFailed'),
|
title: $t('home.getLocationFailed'),
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
})
|
})
|
||||||
} finally {
|
} finally {
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getUserLocationAndAddress = async () => {
|
const getUserLocationAndAddress = async () => {
|
||||||
// 使用腾讯地图SDK获取位置(若失败抛出,由调用方统一处理)
|
// 使用腾讯地图SDK获取位置(若失败抛出,由调用方统一处理)
|
||||||
const location = await getUserLocation()
|
const location = await getUserLocation()
|
||||||
|
|
||||||
if (!location?.longitude || !location?.latitude) {
|
if (!location?.longitude || !location?.latitude) {
|
||||||
throw new Error('invalid location result')
|
throw new Error('invalid location result')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存用户位置
|
// 保存用户位置
|
||||||
userLocation.value = {
|
userLocation.value = {
|
||||||
longitude: location.longitude,
|
|
||||||
latitude: location.latitude
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(userLocation.value);
|
|
||||||
// 将经纬度写入本地缓存(基础信息)
|
|
||||||
try {
|
|
||||||
uni.setStorageSync('userLocation', {
|
|
||||||
longitude: location.longitude,
|
longitude: location.longitude,
|
||||||
latitude: location.latitude
|
latitude: location.latitude
|
||||||
})
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('缓存基础定位信息失败:', e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 只在首次初始化时设置标记
|
|
||||||
if (!isLocationInitialized.value) {
|
|
||||||
isLocationInitialized.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取详细地址信息
|
|
||||||
try {
|
|
||||||
const addressResult = await getRegeo(location.longitude, location.latitude)
|
|
||||||
if (addressResult.success) {
|
|
||||||
const addressInfo = addressResult.data
|
|
||||||
userLocation.value.address = addressInfo.formatted_address
|
|
||||||
userLocation.value.city = addressInfo.addressComponent.city
|
|
||||||
userLocation.value.district = addressInfo.addressComponent.district
|
|
||||||
|
|
||||||
// 更新本地缓存,包含地址信息
|
|
||||||
try {
|
|
||||||
uni.setStorageSync('userLocation', {
|
|
||||||
longitude: userLocation.value.longitude,
|
|
||||||
latitude: userLocation.value.latitude,
|
|
||||||
address: userLocation.value.address,
|
|
||||||
city: userLocation.value.city,
|
|
||||||
district: userLocation.value.district
|
|
||||||
})
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('缓存带地址的定位信息失败:', e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
// 忽略地址信息错误,使用基础定位信息
|
|
||||||
}
|
|
||||||
|
|
||||||
return userLocation.value
|
console.log(userLocation.value);
|
||||||
|
// 将经纬度写入本地缓存(基础信息)
|
||||||
|
try {
|
||||||
|
uni.setStorageSync('userLocation', {
|
||||||
|
longitude: location.longitude,
|
||||||
|
latitude: location.latitude
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('缓存基础定位信息失败:', e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只在首次初始化时设置标记
|
||||||
|
if (!isLocationInitialized.value) {
|
||||||
|
isLocationInitialized.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取详细地址信息
|
||||||
|
try {
|
||||||
|
const addressResult = await getRegeo(location.longitude, location.latitude)
|
||||||
|
if (addressResult.success) {
|
||||||
|
const addressInfo = addressResult.data
|
||||||
|
userLocation.value.address = addressInfo.formatted_address
|
||||||
|
userLocation.value.city = addressInfo.addressComponent.city
|
||||||
|
userLocation.value.district = addressInfo.addressComponent.district
|
||||||
|
|
||||||
|
// 更新本地缓存,包含地址信息
|
||||||
|
try {
|
||||||
|
uni.setStorageSync('userLocation', {
|
||||||
|
longitude: userLocation.value.longitude,
|
||||||
|
latitude: userLocation.value.latitude,
|
||||||
|
address: userLocation.value.address,
|
||||||
|
city: userLocation.value.city,
|
||||||
|
district: userLocation.value.district
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('缓存带地址的定位信息失败:', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// 忽略地址信息错误,使用基础定位信息
|
||||||
|
}
|
||||||
|
|
||||||
|
return userLocation.value
|
||||||
}
|
}
|
||||||
|
|
||||||
const loadPositions = async () => {
|
const loadPositions = async () => {
|
||||||
@@ -890,7 +888,11 @@
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
let deviceNo = getQueryString(scanResult.path, 'deviceNo')
|
// 兼容微信和支付宝小程序的扫码结果结构
|
||||||
|
// 微信小程序:scanResult.path
|
||||||
|
// 支付宝小程序:scanResult.result
|
||||||
|
const scanPath = scanResult.path || scanResult.result || ''
|
||||||
|
let deviceNo = getQueryString(scanPath, 'deviceNo')
|
||||||
|
|
||||||
if (!deviceNo) {
|
if (!deviceNo) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
@@ -1079,10 +1081,13 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
/* 支付宝小程序页面背景色通过外层 view 设置 */
|
||||||
.container {
|
.container {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
min-height: 100vh;
|
||||||
|
/* 支付宝小程序需要设置 min-height */
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-12
@@ -8,16 +8,16 @@
|
|||||||
<view class="title">{{ $t('auth.loginTitle') }}</view>
|
<view class="title">{{ $t('auth.loginTitle') }}</view>
|
||||||
<view class="subtitle">{{ $t('auth.loginDesc') }}</view>
|
<view class="subtitle">{{ $t('auth.loginDesc') }}</view>
|
||||||
|
|
||||||
<!-- 微信一键手机号快捷登录(推荐) -->
|
<!-- 支付宝一键手机号快捷登录(推荐) -->
|
||||||
<button v-if="!isAgreed" class="btn primary" @click="handleLoginClick">
|
<button v-if="!isAgreed" class="btn primary" @click="handleLoginClick">
|
||||||
{{ $t('auth.getPhoneNumber') }}
|
{{ $t('auth.getPhoneNumber') }}
|
||||||
</button>
|
</button>
|
||||||
<button v-else class="btn primary" open-type="getPhoneNumber" @getphonenumber="onGetPhoneNumber">
|
<button v-else class="btn primary" open-type="getAuthorize" scope="phoneNumber" @getAuthorize="onGetPhoneNumber">
|
||||||
{{ $t('auth.getPhoneNumber') }}
|
{{ $t('auth.getPhoneNumber') }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- 仅微信登录(不授权手机号时使用) -->
|
<!-- 仅支付宝登录(不授权手机号时使用) -->
|
||||||
<!-- <button class="btn outline" @click="onWeChatLogin">仅微信登录</button> -->
|
<!-- <button class="btn outline" @click="onAlipayLogin">仅支付宝登录</button> -->
|
||||||
|
|
||||||
<view class="agreement-box">
|
<view class="agreement-box">
|
||||||
<checkbox-group @change="onAgreementChange">
|
<checkbox-group @change="onAgreementChange">
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { onLoad } from '@dcloudio/uni-app'
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
import { wxLogin, getUserPhoneNumber, getUserInfo } from '../../util/index.js'
|
import { alipayLogin, getUserPhoneNumber, getUserInfo } from '../../util/index.js'
|
||||||
import { useI18n } from '@/utils/i18n.js'
|
import { useI18n } from '@/utils/i18n.js'
|
||||||
|
|
||||||
const { t: $t } = useI18n()
|
const { t: $t } = useI18n()
|
||||||
@@ -113,12 +113,12 @@
|
|||||||
uni.reLaunch({ url: target })
|
uni.reLaunch({ url: target })
|
||||||
}
|
}
|
||||||
|
|
||||||
const onWeChatLogin = async () => {
|
const onAlipayLogin = async () => {
|
||||||
try {
|
try {
|
||||||
// 先检查是否同意协议
|
// 先检查是否同意协议
|
||||||
await checkAgreement()
|
await checkAgreement()
|
||||||
|
|
||||||
await wxLogin()
|
await alipayLogin()
|
||||||
uni.showToast({ title: $t('auth.loginSuccess'), icon: 'success' })
|
uni.showToast({ title: $t('auth.loginSuccess'), icon: 'success' })
|
||||||
await navigateAfterLogin()
|
await navigateAfterLogin()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -129,16 +129,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onGetPhoneNumber = async (e) => {
|
const onGetPhoneNumber = async (e) => {
|
||||||
if (!e || e.detail.errMsg !== 'getPhoneNumber:ok') {
|
// 支付宝获取手机号的回调处理
|
||||||
|
if (!e || !e.detail || !e.detail.response) {
|
||||||
uni.showToast({ title: $t('auth.phoneCancelled'), icon: 'none' })
|
uni.showToast({ title: $t('auth.phoneCancelled'), icon: 'none' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 先微信登录,获取 token
|
// 先支付宝登录,获取 token
|
||||||
await wxLogin()
|
await alipayLogin()
|
||||||
// 再用微信返回的临时 code 换取手机号
|
// 再用支付宝返回的授权码换取手机号
|
||||||
await getUserPhoneNumber(e.detail.code)
|
// 支付宝的授权码在 e.detail.response 中
|
||||||
|
const authCode = e.detail.response?.response?.code || e.detail.response?.code
|
||||||
|
if (authCode) {
|
||||||
|
await getUserPhoneNumber(authCode)
|
||||||
|
}
|
||||||
uni.showToast({ title: $t('auth.loginSuccess'), icon: 'success' })
|
uni.showToast({ title: $t('auth.loginSuccess'), icon: 'success' })
|
||||||
await navigateAfterLogin()
|
await navigateAfterLogin()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
+27
-55
@@ -9,7 +9,7 @@
|
|||||||
<view class="nickname">{{ userInfo.nickName || $t('user.clickToLogin') }}</view>
|
<view class="nickname">{{ userInfo.nickName || $t('user.clickToLogin') }}</view>
|
||||||
<view class="subtext">{{ userInfo.phone ? maskPhone(userInfo.phone) : $t('user.loginPrompt') }}</view>
|
<view class="subtext">{{ userInfo.phone ? maskPhone(userInfo.phone) : $t('user.loginPrompt') }}</view>
|
||||||
</view>
|
</view>
|
||||||
<uv-icon type="right" size="16" color="#999"></uv-icon>
|
<uv-icon name="arrow-right" size="16" color="#999"></uv-icon>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@
|
|||||||
<u-popup ref="authPopup" mode="center" border-radius="15" width="600rpx" @open="onPopupOpen" @close="onPopupClose">
|
<u-popup ref="authPopup" mode="center" border-radius="15" width="600rpx" @open="onPopupOpen" @close="onPopupClose">
|
||||||
<view class="auth-popup">
|
<view class="auth-popup">
|
||||||
<view class="auth-title">授权登录</view>
|
<view class="auth-title">授权登录</view>
|
||||||
<view class="auth-desc">获取您的微信头像、昵称等公开信息</view>
|
<view class="auth-desc">获取您的支付宝头像、昵称等公开信息</view>
|
||||||
<view class="auth-buttons">
|
<view class="auth-buttons">
|
||||||
<button class="cancel-btn" @click="closeAuthPopup">取消</button>
|
<button class="cancel-btn" @click="closeAuthPopup">取消</button>
|
||||||
<button class="confirm-btn" @click="getUserProfile">确定</button>
|
<button class="confirm-btn" @click="getUserProfile">确定</button>
|
||||||
@@ -135,7 +135,7 @@
|
|||||||
} from '@dcloudio/uni-app';
|
} from '@dcloudio/uni-app';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
wxLogin,
|
alipayLogin,
|
||||||
getUserInfo
|
getUserInfo
|
||||||
} from '../../util/index.js';
|
} from '../../util/index.js';
|
||||||
import {
|
import {
|
||||||
@@ -184,7 +184,7 @@ import {
|
|||||||
'Content-Language': languageCode
|
'Content-Language': languageCode
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
appPlatform: 'wechat', // 微信平台
|
appPlatform: 'alipay', // 支付宝平台
|
||||||
appType: 'user' // 用户端
|
appType: 'user' // 用户端
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -267,11 +267,12 @@ import {
|
|||||||
|
|
||||||
// 初始化应用版本号(多端兼容,取可用信息)
|
// 初始化应用版本号(多端兼容,取可用信息)
|
||||||
const initVersion = () => {
|
const initVersion = () => {
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-ALIPAY
|
||||||
try {
|
try {
|
||||||
const info = wx.getAccountInfoSync && wx.getAccountInfoSync();
|
// 支付宝小程序获取版本号
|
||||||
if (info && info.miniProgram && info.miniProgram.version) {
|
const systemInfo = uni.getSystemInfoSync();
|
||||||
appVersion.value = info.miniProgram.version;
|
if (systemInfo && systemInfo.version) {
|
||||||
|
appVersion.value = systemInfo.version;
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
// #endif
|
// #endif
|
||||||
@@ -368,12 +369,13 @@ import {
|
|||||||
redirectToLogin()
|
redirectToLogin()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-ALIPAY
|
||||||
getUserProfile()
|
// 支付宝小程序通过页面跳转处理用户资料
|
||||||
|
navigateTo('/pages/userProfile/index')
|
||||||
// #endif
|
// #endif
|
||||||
// #ifndef MP-WEIXIN
|
// #ifndef MP-ALIPAY
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: $t('auth.pleaseUseInWechat'),
|
title: $t('auth.pleaseUseInAlipay'),
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
})
|
})
|
||||||
// #endif
|
// #endif
|
||||||
@@ -446,65 +448,35 @@ import {
|
|||||||
// 这里可以添加弹窗关闭后的逻辑
|
// 这里可以添加弹窗关闭后的逻辑
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取微信用户个人信息
|
// 获取支付宝用户个人信息(已废弃,使用页面跳转方式)
|
||||||
const getUserProfile = () => {
|
const getUserProfile = () => {
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-ALIPAY
|
||||||
uni.showLoading({
|
// 支付宝小程序通过页面跳转处理用户资料
|
||||||
title: $t('common.getting'),
|
navigateTo('/pages/userProfile/index')
|
||||||
mask: true
|
|
||||||
});
|
|
||||||
|
|
||||||
wx.getUserProfile({
|
|
||||||
desc: '用于完善会员资料',
|
|
||||||
success: (res) => {
|
|
||||||
console.log('获取用户信息成功:', res);
|
|
||||||
updateUserInfo(res.userInfo);
|
|
||||||
uploadAvatarAndRefresh(res.userInfo);
|
|
||||||
},
|
|
||||||
fail: (err) => {
|
|
||||||
console.error('获取用户信息失败:', err);
|
|
||||||
uni.showToast({
|
|
||||||
title: '获取用户信息失败',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
},
|
|
||||||
complete: () => {
|
|
||||||
uni.hideLoading();
|
|
||||||
closeAuthPopup();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifndef MP-WEIXIN
|
// #ifndef MP-ALIPAY
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: $t('auth.pleaseUseInWechat'),
|
title: $t('auth.pleaseUseInAlipay'),
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
});
|
});
|
||||||
closeAuthPopup();
|
closeAuthPopup();
|
||||||
// #endif
|
// #endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// 更新用户信息
|
// 更新用户信息(支付宝小程序通过页面跳转处理)
|
||||||
const updateUserInfo = async (wxUserInfo) => {
|
const updateUserInfo = async (alipayUserInfo) => {
|
||||||
try {
|
try {
|
||||||
// 更新本地用户信息
|
// 更新本地用户信息
|
||||||
const updatedInfo = {
|
const updatedInfo = {
|
||||||
...userInfo.value,
|
...userInfo.value,
|
||||||
nickName: wxUserInfo.nickName,
|
nickName: alipayUserInfo.nickName,
|
||||||
avatar: wxUserInfo.avatarUrl
|
avatar: alipayUserInfo.avatarUrl
|
||||||
};
|
};
|
||||||
|
|
||||||
userInfo.value = updatedInfo;
|
userInfo.value = updatedInfo;
|
||||||
uni.setStorageSync('userInfo', updatedInfo);
|
uni.setStorageSync('userInfo', updatedInfo);
|
||||||
|
|
||||||
// 这里可以添加调用后端API更新用户信息的代码
|
|
||||||
// const updateRes = await updateUserInfoApi({
|
|
||||||
// openId: openId.value,
|
|
||||||
// nickName: wxUserInfo.nickName,
|
|
||||||
// avatarUrl: wxUserInfo.avatarUrl,
|
|
||||||
// gender: wxUserInfo.gender
|
|
||||||
// });
|
|
||||||
|
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: $t('user.updateSuccess'),
|
title: $t('user.updateSuccess'),
|
||||||
icon: 'success'
|
icon: 'success'
|
||||||
@@ -522,9 +494,9 @@ import {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 下载并上传头像,更新用户信息
|
// 下载并上传头像,更新用户信息
|
||||||
const uploadAvatarAndRefresh = async (wxUserInfo) => {
|
const uploadAvatarAndRefresh = async (alipayUserInfo) => {
|
||||||
try {
|
try {
|
||||||
const avatarUrl = wxUserInfo?.avatarUrl
|
const avatarUrl = alipayUserInfo?.avatarUrl
|
||||||
if (!avatarUrl) {
|
if (!avatarUrl) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '未获取到头像地址',
|
title: '未获取到头像地址',
|
||||||
@@ -532,7 +504,7 @@ import {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 下载微信头像为本地临时文件
|
// 下载支付宝头像为本地临时文件
|
||||||
const tempFilePath = await new Promise((resolve, reject) => {
|
const tempFilePath = await new Promise((resolve, reject) => {
|
||||||
uni.downloadFile({
|
uni.downloadFile({
|
||||||
url: avatarUrl,
|
url: avatarUrl,
|
||||||
|
|||||||
@@ -271,9 +271,9 @@
|
|||||||
title: $t('common.processing')
|
title: $t('common.processing')
|
||||||
});
|
});
|
||||||
|
|
||||||
// 调用后端创建微信支付订单接口
|
// 调用后端创建支付宝支付订单接口
|
||||||
const res = await uni.request({
|
const res = await uni.request({
|
||||||
url: `${URL || 'http://127.0.0.1:8080'}/app/wx-payment/create/${order.orderNo}`,
|
url: `${URL || 'http://127.0.0.1:8080'}/app/alipay-payment/create/${order.orderNo}`,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
header: {
|
header: {
|
||||||
'Authorization': "Bearer " + uni.getStorageSync('token'),
|
'Authorization': "Bearer " + uni.getStorageSync('token'),
|
||||||
@@ -284,8 +284,9 @@
|
|||||||
if (res.statusCode === 200 && res.data.code === 200) {
|
if (res.statusCode === 200 && res.data.code === 200) {
|
||||||
const payParams = res.data.data;
|
const payParams = res.data.data;
|
||||||
|
|
||||||
// 调用微信支付
|
// 调用支付宝支付
|
||||||
await uni.requestPayment({
|
await uni.requestPayment({
|
||||||
|
provider: 'alipay',
|
||||||
...payParams,
|
...payParams,
|
||||||
success: async () => {
|
success: async () => {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
|
|||||||
@@ -246,9 +246,9 @@ export default {
|
|||||||
title: this.$t('common.processing')
|
title: this.$t('common.processing')
|
||||||
})
|
})
|
||||||
|
|
||||||
// 调用后端创建微信支付订单接口
|
// 调用后端创建支付宝支付订单接口
|
||||||
const res = await uni.request({
|
const res = await uni.request({
|
||||||
url: `${URL || 'http://127.0.0.1:8080'}/app/wx-payment/create/${this.orderInfo.orderNo}`,
|
url: `${URL || 'http://127.0.0.1:8080'}/app/alipay-payment/create/${this.orderInfo.orderNo}`,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
header: {
|
header: {
|
||||||
'Authorization': "Bearer " + uni.getStorageSync('token'),
|
'Authorization': "Bearer " + uni.getStorageSync('token'),
|
||||||
@@ -259,8 +259,9 @@ export default {
|
|||||||
if (res.statusCode === 200 && res.data.code === 200) {
|
if (res.statusCode === 200 && res.data.code === 200) {
|
||||||
const payParams = res.data.data
|
const payParams = res.data.data
|
||||||
|
|
||||||
// 调用微信支付
|
// 调用支付宝支付
|
||||||
await uni.requestPayment({
|
await uni.requestPayment({
|
||||||
|
provider: 'alipay',
|
||||||
...payParams,
|
...payParams,
|
||||||
success: async () => {
|
success: async () => {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
@@ -373,11 +374,11 @@ export default {
|
|||||||
return `${year}-${month}-${day} ${hour}:${minute}`
|
return `${year}-${month}-${day} ${hour}:${minute}`
|
||||||
},
|
},
|
||||||
|
|
||||||
// 检查订单状态(单次查询,不轮询)
|
// 检查订单状态(单次查询,不轮询)
|
||||||
async checkOrderStatus() {
|
async checkOrderStatus() {
|
||||||
try {
|
try {
|
||||||
const res = await uni.request({
|
const res = await uni.request({
|
||||||
url: `${URL || 'http://127.0.0.1:8080'}/app/wx-payment/status/${this.orderInfo.orderNo}`,
|
url: `${URL || 'http://127.0.0.1:8080'}/app/alipay-payment/status/${this.orderInfo.orderNo}`,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
header: {
|
header: {
|
||||||
'Authorization': "Bearer " + uni.getStorageSync('token'),
|
'Authorization': "Bearer " + uni.getStorageSync('token'),
|
||||||
|
|||||||
@@ -15,21 +15,21 @@
|
|||||||
|
|
||||||
<!-- 支付方式标识 -->
|
<!-- 支付方式标识 -->
|
||||||
<view class="device-right">
|
<view class="device-right">
|
||||||
<!-- 微信支付分标识 -->
|
<!-- 支付宝信用免押标识 -->
|
||||||
<view class="payment-badge wx-score" v-if="orderInfo.payWay == 'wx_score_pay'">
|
<view class="payment-badge alipay-score" v-if="orderInfo.payWay == 'alipay_score_pay' || orderInfo.payWay == 'wx_score_pay'">
|
||||||
<image src="/static/images/wxpayflag.png" mode="aspectFit" class="badge-icon"></image>
|
<image src="/static/images/alipay.svg" mode="aspectFit" class="badge-icon"></image>
|
||||||
<view class="badge-text">
|
<view class="badge-text">
|
||||||
<text>{{ $t('order.wxPayScore') }}</text>
|
<text>{{ $t('order.alipayScore') }}</text>
|
||||||
<text class="divider">|</text>
|
<text class="divider">|</text>
|
||||||
<text class="highlight">{{ $t('order.depositFree') }}</text>
|
<text class="highlight">{{ $t('order.depositFree') }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- 会员订单标识 -->
|
<!-- 会员订单标识 -->
|
||||||
<view class="payment-badge member" v-else-if="orderInfo.payWay == 'wx_member_pay'">
|
<view class="payment-badge member" v-else-if="orderInfo.payWay == 'alipay_member_pay' || orderInfo.payWay == 'wx_member_pay'">
|
||||||
<text class="badge-text">{{ $t('order.memberOrder') }}</text>
|
<text class="badge-text">{{ $t('order.memberOrder') }}</text>
|
||||||
</view>
|
</view>
|
||||||
<!-- 微信支付(押金)标识 -->
|
<!-- 支付宝支付(押金)标识 -->
|
||||||
<view class="payment-badge deposit" v-else-if="orderInfo.payWay == 'wx_pay'">
|
<view class="payment-badge deposit" v-else-if="orderInfo.payWay == 'alipay_pay' || orderInfo.payWay == 'wx_pay'">
|
||||||
<text class="badge-text">{{ $t('order.depositPay') }}</text>
|
<text class="badge-text">{{ $t('order.depositPay') }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -322,7 +322,7 @@
|
|||||||
this.countdownTimer = null
|
this.countdownTimer = null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 解析开始时间字符串为时间戳(毫秒),兼容常见格式及 iOS/微信环境
|
// 解析开始时间字符串为时间戳(毫秒),兼容常见格式及 iOS/支付宝环境
|
||||||
parseStartTimeToMs(timeStr) {
|
parseStartTimeToMs(timeStr) {
|
||||||
if (!timeStr) return NaN
|
if (!timeStr) return NaN
|
||||||
if (typeof timeStr === 'number') {
|
if (typeof timeStr === 'number') {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
wxLogin,
|
alipayLogin,
|
||||||
} from '../../../util/index'
|
} from '../../../util/index'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
<view class="avatar-container">
|
<view class="avatar-container">
|
||||||
<image class="avatar" v-if="userInfo.avatar" :src="userInfo.avatar" mode="aspectFill"></image>
|
<image class="avatar" v-if="userInfo.avatar" :src="userInfo.avatar" mode="aspectFill"></image>
|
||||||
<image v-else class="avatar" src="@/static/head.png" mode="aspectFill"></image>
|
<image v-else class="avatar" src="@/static/head.png" mode="aspectFill"></image>
|
||||||
<!-- 覆盖在头像上的微信选择头像授权按钮,仅小程序生效 -->
|
<!-- 覆盖在头像上的支付宝选择头像授权按钮,仅小程序生效 -->
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
<!-- #ifdef MP-ALIPAY -->
|
||||||
<button class="avatar-choose-btn" open-type="chooseAvatar" @chooseavatar="onChooseAvatar"></button>
|
<button class="avatar-choose-btn" open-type="chooseAvatar" @chooseavatar="onChooseAvatar"></button>
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
</view>
|
</view>
|
||||||
@@ -282,7 +282,7 @@ function maskPhone(phone) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 仅小程序端存在,此按钮覆盖在头像上捕获点击以触发选择头像 */
|
/* 仅小程序端存在,此按钮覆盖在头像上捕获点击以触发选择头像 */
|
||||||
/* #ifdef MP-WEIXIN */
|
/* #ifdef MP-ALIPAY */
|
||||||
.avatar-choose-btn {
|
.avatar-choose-btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|||||||
+29
-27
@@ -10,12 +10,12 @@ import { getCommonByBrand } from "@/config/api/system"
|
|||||||
import { HELP_CONTENT } from "@/constants/help"
|
import { HELP_CONTENT } from "@/constants/help"
|
||||||
// import { GET_PHONE_NUMBER_URL } from "../config/url"
|
// import { GET_PHONE_NUMBER_URL } from "../config/url"
|
||||||
|
|
||||||
// 微信登录方法
|
// 支付宝登录方法
|
||||||
export const wxLogin = () => {
|
export const alipayLogin = () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// 1. 获取微信登录凭证
|
// 1. 获取支付宝登录凭证
|
||||||
uni.login({
|
uni.login({
|
||||||
provider: 'weixin',
|
provider: 'alipay',
|
||||||
success: async (loginRes) => {
|
success: async (loginRes) => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -23,7 +23,7 @@ export const wxLogin = () => {
|
|||||||
// 2. 发送 code 到后端换取 token
|
// 2. 发送 code 到后端换取 token
|
||||||
const result = await login({
|
const result = await login({
|
||||||
code: loginRes.code,
|
code: loginRes.code,
|
||||||
appid: "wx2165f0be356ae7a9"
|
appid: "2021006117693332"
|
||||||
})
|
})
|
||||||
|
|
||||||
if (result.code === 200) {
|
if (result.code === 200) {
|
||||||
@@ -42,7 +42,7 @@ export const wxLogin = () => {
|
|||||||
throw new Error(result.message || '登录失败')
|
throw new Error(result.message || '登录失败')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error('获取微信登录凭证失败')
|
throw new Error('获取支付宝登录凭证失败')
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ export const wxLogin = () => {
|
|||||||
},
|
},
|
||||||
fail: (error) => {
|
fail: (error) => {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '微信登录失败',
|
title: '支付宝登录失败',
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
})
|
})
|
||||||
reject(error)
|
reject(error)
|
||||||
@@ -64,6 +64,9 @@ export const wxLogin = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 兼容旧代码,保留wxLogin别名
|
||||||
|
export const wxLogin = alipayLogin
|
||||||
|
|
||||||
// 检查登录状态
|
// 检查登录状态
|
||||||
// export const checkLogin = () => {
|
// export const checkLogin = () => {
|
||||||
// const token = uni.getStorageSync('token')
|
// const token = uni.getStorageSync('token')
|
||||||
@@ -104,7 +107,7 @@ export const getUserPhoneNumber = (code) => {
|
|||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
code: code, // 微信获取手机号授权后的临时code
|
code: code, // 支付宝获取手机号授权后的临时code
|
||||||
appid: appid
|
appid: appid
|
||||||
},
|
},
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
@@ -137,34 +140,26 @@ export const getUserPhoneNumber = (code) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调用微信支付分接口
|
// 调用支付宝支付接口
|
||||||
export const initiateWeChatScorePayment = (paymentData) => {
|
export const initiateAlipayPayment = (paymentData) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// 确保paymentData包含所需数据
|
// 确保paymentData包含所需数据
|
||||||
if (!paymentData || !paymentData.data || !paymentData.data.package) {
|
if (!paymentData || !paymentData.data) {
|
||||||
reject(new Error('支付参数不完整'));
|
reject(new Error('支付参数不完整'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用wx.openBusinessView打开微信支付分小程序
|
// 使用uni.requestPayment调用支付宝支付
|
||||||
wx.openBusinessView({
|
uni.requestPayment({
|
||||||
businessType: 'wxpayScoreUse',
|
provider: 'alipay',
|
||||||
extraData: {
|
orderInfo: paymentData.data.orderInfo || paymentData.data,
|
||||||
mch_id: paymentData.data.mch_id,
|
success: (res) => {
|
||||||
package: paymentData.data.package
|
resolve(res);
|
||||||
},
|
|
||||||
success: (businessRes) => {
|
|
||||||
// 根据返回结果判断是否完成支付
|
|
||||||
if (businessRes.errMsg === 'openBusinessView:ok') {
|
|
||||||
resolve(businessRes);
|
|
||||||
} else {
|
|
||||||
reject(new Error('支付流程未完成'));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
fail: (error) => {
|
fail: (error) => {
|
||||||
console.error('微信支付分小程序调用失败', error);
|
console.error('支付宝支付调用失败', error);
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: error.errMsg || '支付分接口调用失败',
|
title: error.errMsg || '支付接口调用失败',
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
});
|
});
|
||||||
reject(error);
|
reject(error);
|
||||||
@@ -173,7 +168,14 @@ export const initiateWeChatScorePayment = (paymentData) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 兼容旧代码,保留旧函数名
|
||||||
|
export const initiateWeChatScorePayment = initiateAlipayPayment
|
||||||
|
|
||||||
export const getQueryString = function(url, name) {
|
export const getQueryString = function(url, name) {
|
||||||
|
// 添加空值检查,兼容支付宝小程序
|
||||||
|
if (!url || typeof url !== 'string') {
|
||||||
|
return null
|
||||||
|
}
|
||||||
var reg = new RegExp('(^|&|/?)' + name + '=([^&|/?]*)(&|/?|$)', 'i')
|
var reg = new RegExp('(^|&|/?)' + name + '=([^&|/?]*)(&|/?|$)', 'i')
|
||||||
var r = url.substr(1).match(reg)
|
var r = url.substr(1).match(reg)
|
||||||
if (r != null) {
|
if (r != null) {
|
||||||
|
|||||||
+614
-19
@@ -39,6 +39,287 @@ const getPermissionText = (key) => {
|
|||||||
// 腾讯地图Key
|
// 腾讯地图Key
|
||||||
const QQMAP_KEY = 'RO5BZ-ECZ63-7US3C-RT5QW-TIDZE-2FF35';
|
const QQMAP_KEY = 'RO5BZ-ECZ63-7US3C-RT5QW-TIDZE-2FF35';
|
||||||
|
|
||||||
|
// 高德地图配置(支付宝小程序专用)
|
||||||
|
const AMAP_KEY = 'a07af802ff0a04f012954ff4e69b36d0';
|
||||||
|
const AMAP_SECURITY_KEY = '119f36535ab42b8b2c857f29f9320b06';
|
||||||
|
const AMAP_BASE_URL = 'https://restapi.amap.com/v3';
|
||||||
|
const AMAP_PATH_PREFIX = '/v3';
|
||||||
|
|
||||||
|
// 运行环境标识(编译期指令)
|
||||||
|
const isAlipayEnv = (() => {
|
||||||
|
let flag = false;
|
||||||
|
// #ifdef MP-ALIPAY
|
||||||
|
flag = true;
|
||||||
|
// #endif
|
||||||
|
return flag;
|
||||||
|
})();
|
||||||
|
|
||||||
|
// 轻量级 MD5 实现(用于生成高德安全 sig)
|
||||||
|
function md5(string) {
|
||||||
|
function RotateLeft(lValue, iShiftBits) {
|
||||||
|
return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
|
||||||
|
}
|
||||||
|
function AddUnsigned(lX, lY) {
|
||||||
|
const lX4 = lX & 0x40000000;
|
||||||
|
const lY4 = lY & 0x40000000;
|
||||||
|
const lX8 = lX & 0x80000000;
|
||||||
|
const lY8 = lY & 0x80000000;
|
||||||
|
const lResult = (lX & 0x3fffffff) + (lY & 0x3fffffff);
|
||||||
|
if (lX4 & lY4) {
|
||||||
|
return lResult ^ 0x80000000 ^ lX8 ^ lY8;
|
||||||
|
}
|
||||||
|
if (lX4 | lY4) {
|
||||||
|
if (lResult & 0x40000000) {
|
||||||
|
return lResult ^ 0xc0000000 ^ lX8 ^ lY8;
|
||||||
|
}
|
||||||
|
return lResult ^ 0x40000000 ^ lX8 ^ lY8;
|
||||||
|
}
|
||||||
|
return lResult ^ lX8 ^ lY8;
|
||||||
|
}
|
||||||
|
function F(x, y, z) { return (x & y) | (~x & z); }
|
||||||
|
function G(x, y, z) { return (x & z) | (y & ~z); }
|
||||||
|
function H(x, y, z) { return x ^ y ^ z; }
|
||||||
|
function I(x, y, z) { return y ^ (x | ~z); }
|
||||||
|
function FF(a, b, c, d, x, s, ac) {
|
||||||
|
a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
|
||||||
|
return AddUnsigned(RotateLeft(a, s), b);
|
||||||
|
}
|
||||||
|
function GG(a, b, c, d, x, s, ac) {
|
||||||
|
a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
|
||||||
|
return AddUnsigned(RotateLeft(a, s), b);
|
||||||
|
}
|
||||||
|
function HH(a, b, c, d, x, s, ac) {
|
||||||
|
a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
|
||||||
|
return AddUnsigned(RotateLeft(a, s), b);
|
||||||
|
}
|
||||||
|
function II(a, b, c, d, x, s, ac) {
|
||||||
|
a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
|
||||||
|
return AddUnsigned(RotateLeft(a, s), b);
|
||||||
|
}
|
||||||
|
function ConvertToWordArray(str) {
|
||||||
|
const lWordArray = [];
|
||||||
|
let lMessageLength = str.length;
|
||||||
|
let lNumberOfWordsTempOne = lMessageLength + 8;
|
||||||
|
const lNumberOfWordsTempTwo = (lNumberOfWordsTempOne - (lNumberOfWordsTempOne % 64)) / 64;
|
||||||
|
const lNumberOfWords = (lNumberOfWordsTempTwo + 1) * 16;
|
||||||
|
let lBytePosition = 0;
|
||||||
|
let lByteCount = 0;
|
||||||
|
while (lByteCount < lMessageLength) {
|
||||||
|
const lWordCount = (lByteCount - (lByteCount % 4)) / 4;
|
||||||
|
lBytePosition = (lByteCount % 4) * 8;
|
||||||
|
lWordArray[lWordCount] = (lWordArray[lWordCount] || 0) | (str.charCodeAt(lByteCount) << lBytePosition);
|
||||||
|
lByteCount++;
|
||||||
|
}
|
||||||
|
const lWordCount = (lByteCount - (lByteCount % 4)) / 4;
|
||||||
|
lBytePosition = (lByteCount % 4) * 8;
|
||||||
|
lWordArray[lWordCount] = lWordArray[lWordCount] || 0;
|
||||||
|
lWordArray[lWordCount] |= 0x80 << lBytePosition;
|
||||||
|
lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
|
||||||
|
lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
|
||||||
|
return lWordArray;
|
||||||
|
}
|
||||||
|
function WordToHex(lValue) {
|
||||||
|
let WordToHexValue = '';
|
||||||
|
for (let lCount = 0; lCount <= 3; lCount++) {
|
||||||
|
const lByte = (lValue >>> (lCount * 8)) & 255;
|
||||||
|
const WordToHexValueTemp = '0' + lByte.toString(16);
|
||||||
|
WordToHexValue += WordToHexValueTemp.substr(WordToHexValueTemp.length - 2, 2);
|
||||||
|
}
|
||||||
|
return WordToHexValue;
|
||||||
|
}
|
||||||
|
function Utf8Encode(str) {
|
||||||
|
str = str.replace(/\r\n/g, '\n');
|
||||||
|
let utftext = '';
|
||||||
|
for (let n = 0; n < str.length; n++) {
|
||||||
|
const c = str.charCodeAt(n);
|
||||||
|
if (c < 128) {
|
||||||
|
utftext += String.fromCharCode(c);
|
||||||
|
} else if (c > 127 && c < 2048) {
|
||||||
|
utftext += String.fromCharCode((c >> 6) | 192);
|
||||||
|
utftext += String.fromCharCode((c & 63) | 128);
|
||||||
|
} else {
|
||||||
|
utftext += String.fromCharCode((c >> 12) | 224);
|
||||||
|
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
||||||
|
utftext += String.fromCharCode((c & 63) | 128);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return utftext;
|
||||||
|
}
|
||||||
|
|
||||||
|
let x = [];
|
||||||
|
let k, AA, BB, CC, DD, a, b, c, d;
|
||||||
|
const S11 = 7, S12 = 12, S13 = 17, S14 = 22;
|
||||||
|
const S21 = 5, S22 = 9, S23 = 14, S24 = 20;
|
||||||
|
const S31 = 4, S32 = 11, S33 = 16, S34 = 23;
|
||||||
|
const S41 = 6, S42 = 10, S43 = 15, S44 = 21;
|
||||||
|
|
||||||
|
string = Utf8Encode(String(string));
|
||||||
|
x = ConvertToWordArray(string);
|
||||||
|
a = 0x67452301;
|
||||||
|
b = 0xefcdab89;
|
||||||
|
c = 0x98badcfe;
|
||||||
|
d = 0x10325476;
|
||||||
|
|
||||||
|
for (k = 0; k < x.length; k += 16) {
|
||||||
|
AA = a; BB = b; CC = c; DD = d;
|
||||||
|
a = FF(a, b, c, d, x[k + 0], S11, 0xd76aa478);
|
||||||
|
d = FF(d, a, b, c, x[k + 1], S12, 0xe8c7b756);
|
||||||
|
c = FF(c, d, a, b, x[k + 2], S13, 0x242070db);
|
||||||
|
b = FF(b, c, d, a, x[k + 3], S14, 0xc1bdceee);
|
||||||
|
a = FF(a, b, c, d, x[k + 4], S11, 0xf57c0faf);
|
||||||
|
d = FF(d, a, b, c, x[k + 5], S12, 0x4787c62a);
|
||||||
|
c = FF(c, d, a, b, x[k + 6], S13, 0xa8304613);
|
||||||
|
b = FF(b, c, d, a, x[k + 7], S14, 0xfd469501);
|
||||||
|
a = FF(a, b, c, d, x[k + 8], S11, 0x698098d8);
|
||||||
|
d = FF(d, a, b, c, x[k + 9], S12, 0x8b44f7af);
|
||||||
|
c = FF(c, d, a, b, x[k + 10], S13, 0xffff5bb1);
|
||||||
|
b = FF(b, c, d, a, x[k + 11], S14, 0x895cd7be);
|
||||||
|
a = FF(a, b, c, d, x[k + 12], S11, 0x6b901122);
|
||||||
|
d = FF(d, a, b, c, x[k + 13], S12, 0xfd987193);
|
||||||
|
c = FF(c, d, a, b, x[k + 14], S13, 0xa679438e);
|
||||||
|
b = FF(b, c, d, a, x[k + 15], S14, 0x49b40821);
|
||||||
|
a = GG(a, b, c, d, x[k + 1], S21, 0xf61e2562);
|
||||||
|
d = GG(d, a, b, c, x[k + 6], S22, 0xc040b340);
|
||||||
|
c = GG(c, d, a, b, x[k + 11], S23, 0x265e5a51);
|
||||||
|
b = GG(b, c, d, a, x[k + 0], S24, 0xe9b6c7aa);
|
||||||
|
a = GG(a, b, c, d, x[k + 5], S21, 0xd62f105d);
|
||||||
|
d = GG(d, a, b, c, x[k + 10], S22, 0x2441453);
|
||||||
|
c = GG(c, d, a, b, x[k + 15], S23, 0xd8a1e681);
|
||||||
|
b = GG(b, c, d, a, x[k + 4], S24, 0xe7d3fbc8);
|
||||||
|
a = GG(a, b, c, d, x[k + 9], S21, 0x21e1cde6);
|
||||||
|
d = GG(d, a, b, c, x[k + 14], S22, 0xc33707d6);
|
||||||
|
c = GG(c, d, a, b, x[k + 3], S23, 0xf4d50d87);
|
||||||
|
b = GG(b, c, d, a, x[k + 8], S24, 0x455a14ed);
|
||||||
|
a = GG(a, b, c, d, x[k + 13], S21, 0xa9e3e905);
|
||||||
|
d = GG(d, a, b, c, x[k + 2], S22, 0xfcefa3f8);
|
||||||
|
c = GG(c, d, a, b, x[k + 7], S23, 0x676f02d9);
|
||||||
|
b = GG(b, c, d, a, x[k + 12], S24, 0x8d2a4c8a);
|
||||||
|
a = HH(a, b, c, d, x[k + 5], S31, 0xfffa3942);
|
||||||
|
d = HH(d, a, b, c, x[k + 8], S32, 0x8771f681);
|
||||||
|
c = HH(c, d, a, b, x[k + 11], S33, 0x6d9d6122);
|
||||||
|
b = HH(b, c, d, a, x[k + 14], S34, 0xfde5380c);
|
||||||
|
a = HH(a, b, c, d, x[k + 1], S31, 0xa4beea44);
|
||||||
|
d = HH(d, a, b, c, x[k + 4], S32, 0x4bdecfa9);
|
||||||
|
c = HH(c, d, a, b, x[k + 7], S33, 0xf6bb4b60);
|
||||||
|
b = HH(b, c, d, a, x[k + 10], S34, 0xbebfbc70);
|
||||||
|
a = HH(a, b, c, d, x[k + 13], S31, 0x289b7ec6);
|
||||||
|
d = HH(d, a, b, c, x[k + 0], S32, 0xeaa127fa);
|
||||||
|
c = HH(c, d, a, b, x[k + 3], S33, 0xd4ef3085);
|
||||||
|
b = HH(b, c, d, a, x[k + 6], S34, 0x4881d05);
|
||||||
|
a = HH(a, b, c, d, x[k + 9], S31, 0xd9d4d039);
|
||||||
|
d = HH(d, a, b, c, x[k + 12], S32, 0xe6db99e5);
|
||||||
|
c = HH(c, d, a, b, x[k + 15], S33, 0x1fa27cf8);
|
||||||
|
b = HH(b, c, d, a, x[k + 2], S34, 0xc4ac5665);
|
||||||
|
a = II(a, b, c, d, x[k + 0], S41, 0xf4292244);
|
||||||
|
d = II(d, a, b, c, x[k + 7], S42, 0x432aff97);
|
||||||
|
c = II(c, d, a, b, x[k + 14], S43, 0xab9423a7);
|
||||||
|
b = II(b, c, d, a, x[k + 5], S44, 0xfc93a039);
|
||||||
|
a = II(a, b, c, d, x[k + 12], S41, 0x655b59c3);
|
||||||
|
d = II(d, a, b, c, x[k + 3], S42, 0x8f0ccc92);
|
||||||
|
c = II(c, d, a, b, x[k + 10], S43, 0xffeff47d);
|
||||||
|
b = II(b, c, d, a, x[k + 1], S44, 0x85845dd1);
|
||||||
|
a = II(a, b, c, d, x[k + 8], S41, 0x6fa87e4f);
|
||||||
|
d = II(d, a, b, c, x[k + 15], S42, 0xfe2ce6e0);
|
||||||
|
c = II(c, d, a, b, x[k + 6], S43, 0xa3014314);
|
||||||
|
b = II(b, c, d, a, x[k + 13], S44, 0x4e0811a1);
|
||||||
|
a = II(a, b, c, d, x[k + 4], S41, 0xf7537e82);
|
||||||
|
d = II(d, a, b, c, x[k + 11], S42, 0xbd3af235);
|
||||||
|
c = II(c, d, a, b, x[k + 2], S43, 0x2ad7d2bb);
|
||||||
|
b = II(b, c, d, a, x[k + 9], S44, 0xeb86d391);
|
||||||
|
a = AddUnsigned(a, AA);
|
||||||
|
b = AddUnsigned(b, BB);
|
||||||
|
c = AddUnsigned(c, CC);
|
||||||
|
d = AddUnsigned(d, DD);
|
||||||
|
}
|
||||||
|
|
||||||
|
const temp = WordToHex(a) + WordToHex(b) + WordToHex(c) + WordToHex(d);
|
||||||
|
return temp.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将参数按字典序拼装为查询字符串
|
||||||
|
function buildSortedQuery(params) {
|
||||||
|
const sortedKeys = Object.keys(params || {}).sort();
|
||||||
|
return sortedKeys.map(key => `${key}=${params[key] !== undefined ? params[key] : ''}`).join('&');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调试开关:如需打印签名原串和 sig,临时改为 true
|
||||||
|
const DEBUG_AMAP_SIG = false;
|
||||||
|
|
||||||
|
// 构造高德 API 签名(正确规则:参数字符串 + 私钥,不含路径)
|
||||||
|
function buildAmapSig(params) {
|
||||||
|
const query = buildSortedQuery(params);
|
||||||
|
const raw = `${query}${AMAP_SECURITY_KEY}`;
|
||||||
|
if (DEBUG_AMAP_SIG) {
|
||||||
|
console.log('[AMap Sig Debug] query:', query, 'raw:', raw, 'sig:', md5(raw));
|
||||||
|
}
|
||||||
|
return md5(raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 过滤掉 undefined / null 参数,避免签名与请求不一致
|
||||||
|
function sanitizeParams(obj = {}) {
|
||||||
|
const cleaned = {};
|
||||||
|
Object.keys(obj).forEach((k) => {
|
||||||
|
const v = obj[k];
|
||||||
|
if (v !== undefined && v !== null) {
|
||||||
|
cleaned[k] = v;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return cleaned;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统一的高德 API 请求
|
||||||
|
function requestAmap(path, params = {}) {
|
||||||
|
const normalizedPath = path.startsWith('/') ? path : `/${path}`;
|
||||||
|
const baseParams = sanitizeParams({
|
||||||
|
key: AMAP_KEY,
|
||||||
|
...params
|
||||||
|
});
|
||||||
|
const sig = buildAmapSig(baseParams);
|
||||||
|
const queryParams = sanitizeParams({
|
||||||
|
...baseParams,
|
||||||
|
sig
|
||||||
|
});
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.request({
|
||||||
|
url: `${AMAP_BASE_URL}${normalizedPath}`,
|
||||||
|
method: 'GET',
|
||||||
|
data: queryParams,
|
||||||
|
success: (res) => {
|
||||||
|
if (res.data && res.data.status === '1') {
|
||||||
|
resolve(res.data);
|
||||||
|
} else {
|
||||||
|
reject(res.data || { message: 'AMap request failed' });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: reject
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将 WGS84 转 GCJ02(支付宝 my.getLocation 返回 WGS84)
|
||||||
|
async function convertToGcj02(longitude, latitude) {
|
||||||
|
if (!isAlipayEnv) {
|
||||||
|
return { longitude, latitude };
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const data = await requestAmap('/assistant/coordinate/convert', {
|
||||||
|
locations: `${longitude},${latitude}`,
|
||||||
|
coordsys: 'gps' // gps 即 WGS84
|
||||||
|
});
|
||||||
|
const locStr = (data.locations || '').split(';')[0] || '';
|
||||||
|
const [lngStr, latStr] = locStr.split(',');
|
||||||
|
const lng = Number(lngStr);
|
||||||
|
const lat = Number(latStr);
|
||||||
|
if (!isNaN(lng) && !isNaN(lat)) {
|
||||||
|
return { longitude: lng, latitude: lat };
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('坐标转换失败,使用原始坐标:', err);
|
||||||
|
}
|
||||||
|
return { longitude, latitude };
|
||||||
|
}
|
||||||
|
|
||||||
// 内联腾讯地图SDK核心代码
|
// 内联腾讯地图SDK核心代码
|
||||||
const QQMapWX = (function() {
|
const QQMapWX = (function() {
|
||||||
// 错误配置
|
// 错误配置
|
||||||
@@ -118,22 +399,55 @@ const QQMapWX = (function() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (!param.location) {
|
if (!param.location) {
|
||||||
|
// 微信小程序使用 wx.getLocation
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
wx.getLocation({
|
wx.getLocation({
|
||||||
type: 'gcj02',
|
type: 'gcj02',
|
||||||
success: locationsuccess,
|
success: locationsuccess,
|
||||||
fail: locationfail,
|
fail: locationfail,
|
||||||
complete: locationcomplete
|
complete: locationcomplete
|
||||||
});
|
});
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// 支付宝小程序使用 my.getLocation(不支持 type)
|
||||||
|
// #ifdef MP-ALIPAY
|
||||||
|
my.getLocation({
|
||||||
|
success: (res) => {
|
||||||
|
// 确保经纬度是数字类型
|
||||||
|
const result = {
|
||||||
|
...res,
|
||||||
|
longitude: Number(res.longitude),
|
||||||
|
latitude: Number(res.latitude)
|
||||||
|
};
|
||||||
|
locationsuccess(result);
|
||||||
|
},
|
||||||
|
fail: locationfail,
|
||||||
|
complete: locationcomplete
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// 其他平台使用 uni.getLocation
|
||||||
|
// #ifndef MP-WEIXIN
|
||||||
|
// #ifndef MP-ALIPAY
|
||||||
|
uni.getLocation({
|
||||||
|
type: 'gcj02',
|
||||||
|
success: locationsuccess,
|
||||||
|
fail: locationfail,
|
||||||
|
complete: locationcomplete
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
// #endif
|
||||||
} else if (that.checkLocation(param)) {
|
} else if (that.checkLocation(param)) {
|
||||||
const location = Utils.getLocationParam(param.location);
|
const location = Utils.getLocationParam(param.location);
|
||||||
locationsuccess(location);
|
locationsuccess(location);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 构造微信请求参数
|
// 构造腾讯地图API请求参数(跨平台兼容)
|
||||||
buildWxRequestConfig(param, options, feature) {
|
buildWxRequestConfig(param, options, feature) {
|
||||||
const that = this;
|
const that = this;
|
||||||
options.header = { "content-type": "application/json" };
|
// GET请求不需要设置content-type,uni.request会自动处理
|
||||||
|
options.header = options.header || {};
|
||||||
options.method = 'GET';
|
options.method = 'GET';
|
||||||
options.success = function (res) {
|
options.success = function (res) {
|
||||||
const data = res.data;
|
const data = res.data;
|
||||||
@@ -280,8 +594,10 @@ const QQMapWX = (function() {
|
|||||||
|
|
||||||
const locationsuccess = function (result) {
|
const locationsuccess = function (result) {
|
||||||
requestParam.location = result.latitude + ',' + result.longitude;
|
requestParam.location = result.latitude + ',' + result.longitude;
|
||||||
wx.request(Utils.buildWxRequestConfig(options, {
|
// 调用腾讯地图API - 逆地理编码接口
|
||||||
url: URL_GET_GEOCODER,
|
// 使用 uni.request 跨平台API,在支付宝小程序中自动转换为 my.request
|
||||||
|
uni.request(Utils.buildWxRequestConfig(options, {
|
||||||
|
url: URL_GET_GEOCODER, // 腾讯地图API地址:https://apis.map.qq.com/ws/geocoder/v1/
|
||||||
data: requestParam
|
data: requestParam
|
||||||
}, 'reverseGeocoder'));
|
}, 'reverseGeocoder'));
|
||||||
};
|
};
|
||||||
@@ -323,8 +639,10 @@ const QQMapWX = (function() {
|
|||||||
|
|
||||||
const locationsuccess = function (result) {
|
const locationsuccess = function (result) {
|
||||||
requestParam.boundary = "nearby(" + result.latitude + "," + result.longitude + "," + distance + "," + auto_extend + ")";
|
requestParam.boundary = "nearby(" + result.latitude + "," + result.longitude + "," + distance + "," + auto_extend + ")";
|
||||||
wx.request(Utils.buildWxRequestConfig(options, {
|
// 调用腾讯地图API - POI周边检索接口
|
||||||
url: URL_SEARCH,
|
// 使用 uni.request 跨平台API,在支付宝小程序中自动转换为 my.request
|
||||||
|
uni.request(Utils.buildWxRequestConfig(options, {
|
||||||
|
url: URL_SEARCH, // 腾讯地图API地址:https://apis.map.qq.com/ws/place/v1/search
|
||||||
data: requestParam
|
data: requestParam
|
||||||
}, 'search'));
|
}, 'search'));
|
||||||
};
|
};
|
||||||
@@ -368,15 +686,19 @@ const QQMapWX = (function() {
|
|||||||
if (options.location) {
|
if (options.location) {
|
||||||
const locationsuccess = function (result) {
|
const locationsuccess = function (result) {
|
||||||
requestParam.location = result.latitude + ',' + result.longitude;
|
requestParam.location = result.latitude + ',' + result.longitude;
|
||||||
wx.request(Utils.buildWxRequestConfig(options, {
|
// 调用腾讯地图API - 地点搜索建议接口
|
||||||
url: URL_SUGGESTION,
|
// 使用 uni.request 跨平台API,在支付宝小程序中自动转换为 my.request
|
||||||
|
uni.request(Utils.buildWxRequestConfig(options, {
|
||||||
|
url: URL_SUGGESTION, // 腾讯地图API地址:https://apis.map.qq.com/ws/place/v1/suggestion
|
||||||
data: requestParam
|
data: requestParam
|
||||||
}, "suggest"));
|
}, "suggest"));
|
||||||
};
|
};
|
||||||
Utils.locationProcess(options, locationsuccess);
|
Utils.locationProcess(options, locationsuccess);
|
||||||
} else {
|
} else {
|
||||||
wx.request(Utils.buildWxRequestConfig(options, {
|
// 调用腾讯地图API - 地点搜索建议接口(无位置信息)
|
||||||
url: URL_SUGGESTION,
|
// 使用 uni.request 跨平台API,在支付宝小程序中自动转换为 my.request
|
||||||
|
uni.request(Utils.buildWxRequestConfig(options, {
|
||||||
|
url: URL_SUGGESTION, // 腾讯地图API地址:https://apis.map.qq.com/ws/place/v1/suggestion
|
||||||
data: requestParam
|
data: requestParam
|
||||||
}, "suggest"));
|
}, "suggest"));
|
||||||
}
|
}
|
||||||
@@ -408,8 +730,10 @@ const QQMapWX = (function() {
|
|||||||
|
|
||||||
const locationsuccess = function (result) {
|
const locationsuccess = function (result) {
|
||||||
requestParam.from = result.latitude + ',' + result.longitude;
|
requestParam.from = result.latitude + ',' + result.longitude;
|
||||||
wx.request(Utils.buildWxRequestConfig(options, {
|
// 调用腾讯地图API - 距离计算接口
|
||||||
url: URL_DISTANCE,
|
// 使用 uni.request 跨平台API,在支付宝小程序中自动转换为 my.request
|
||||||
|
uni.request(Utils.buildWxRequestConfig(options, {
|
||||||
|
url: URL_DISTANCE, // 腾讯地图API地址:https://apis.map.qq.com/ws/distance/v1/
|
||||||
data: requestParam
|
data: requestParam
|
||||||
}, 'calculateDistance'));
|
}, 'calculateDistance'));
|
||||||
};
|
};
|
||||||
@@ -426,6 +750,10 @@ let qqmapInstance = null;
|
|||||||
|
|
||||||
// 初始化腾讯地图SDK
|
// 初始化腾讯地图SDK
|
||||||
function initQQMap() {
|
function initQQMap() {
|
||||||
|
if (isAlipayEnv) {
|
||||||
|
// 支付宝端改用高德地图服务
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (!qqmapInstance) {
|
if (!qqmapInstance) {
|
||||||
try {
|
try {
|
||||||
qqmapInstance = new QQMapWX({
|
qqmapInstance = new QQMapWX({
|
||||||
@@ -441,6 +769,9 @@ function initQQMap() {
|
|||||||
|
|
||||||
// 获取腾讯地图SDK实例
|
// 获取腾讯地图SDK实例
|
||||||
function getQQMapInstance() {
|
function getQQMapInstance() {
|
||||||
|
if (isAlipayEnv) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return qqmapInstance || initQQMap();
|
return qqmapInstance || initQQMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,8 +818,9 @@ function getUserLocation() {
|
|||||||
wx.getLocation({
|
wx.getLocation({
|
||||||
type: 'gcj02',
|
type: 'gcj02',
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
const longitude = parseFloat(res.longitude.toFixed(5));
|
// 确保经纬度是数字类型
|
||||||
const latitude = parseFloat(res.latitude.toFixed(5));
|
const longitude = parseFloat(Number(res.longitude).toFixed(5));
|
||||||
|
const latitude = parseFloat(Number(res.latitude).toFixed(5));
|
||||||
console.log('地址获取成功');
|
console.log('地址获取成功');
|
||||||
resolve({
|
resolve({
|
||||||
longitude,
|
longitude,
|
||||||
@@ -533,8 +865,9 @@ function getUserLocation() {
|
|||||||
wx.getLocation({
|
wx.getLocation({
|
||||||
type: 'gcj02',
|
type: 'gcj02',
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
const longitude = parseFloat(res.longitude.toFixed(5));
|
// 确保经纬度是数字类型
|
||||||
const latitude = parseFloat(res.latitude.toFixed(5));
|
const longitude = parseFloat(Number(res.longitude).toFixed(5));
|
||||||
|
const latitude = parseFloat(Number(res.latitude).toFixed(5));
|
||||||
console.log('地址获取成功');
|
console.log('地址获取成功');
|
||||||
resolve({
|
resolve({
|
||||||
longitude,
|
longitude,
|
||||||
@@ -550,13 +883,114 @@ function getUserLocation() {
|
|||||||
});
|
});
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// 非微信小程序平台:使用 uni.getLocation 做一个尽量兼容的兜底
|
// 支付宝小程序:使用 my.getLocation API,不支持 type 参数
|
||||||
|
// #ifdef MP-ALIPAY
|
||||||
|
// 支付宝小程序权限检查
|
||||||
|
my.getSetting({
|
||||||
|
success: (settingRes) => {
|
||||||
|
const authSetting = settingRes.authSetting || {};
|
||||||
|
const hasLocationAuth = Object.prototype.hasOwnProperty.call(authSetting, 'location');
|
||||||
|
const locationAuth = authSetting['location'];
|
||||||
|
|
||||||
|
// 已明确拒绝定位
|
||||||
|
if (locationAuth === false) {
|
||||||
|
my.showModal({
|
||||||
|
title: getPermissionText('locationTitle'),
|
||||||
|
content: getPermissionText('locationNeed'),
|
||||||
|
confirmText: getPermissionText('goToSettings'),
|
||||||
|
cancelText: getPermissionText('later'),
|
||||||
|
success: (modalRes) => {
|
||||||
|
if (modalRes.confirm) {
|
||||||
|
my.openSetting({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
reject({
|
||||||
|
code: 'LOCATION_DENIED',
|
||||||
|
errMsg: 'user denied location permission'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const doGetLocation = () => {
|
||||||
|
// 支付宝小程序使用 my.getLocation,不支持 type 参数
|
||||||
|
my.getLocation({
|
||||||
|
success: (res) => {
|
||||||
|
// 支付宝小程序返回的经纬度可能是字符串,需要先转换为数字
|
||||||
|
// 注意:支付宝返回的是 WGS84 坐标系,如需 GCJ02 需要转换
|
||||||
|
const longitude = parseFloat(Number(res.longitude).toFixed(5));
|
||||||
|
const latitude = parseFloat(Number(res.latitude).toFixed(5));
|
||||||
|
console.log('支付宝地址获取成功');
|
||||||
|
resolve({
|
||||||
|
longitude,
|
||||||
|
latitude
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: (error) => {
|
||||||
|
console.error('获取位置失败:', error);
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 未显式授权时,主动申请一次权限
|
||||||
|
if (!hasLocationAuth || locationAuth === undefined) {
|
||||||
|
my.authorize({
|
||||||
|
scope: 'scope.userLocation',
|
||||||
|
success: () => {
|
||||||
|
doGetLocation();
|
||||||
|
},
|
||||||
|
fail: (authErr) => {
|
||||||
|
console.error('定位授权失败:', authErr);
|
||||||
|
my.showModal({
|
||||||
|
title: getPermissionText('locationTitle'),
|
||||||
|
content: getPermissionText('locationDenied'),
|
||||||
|
confirmText: getPermissionText('gotIt'),
|
||||||
|
showCancel: false
|
||||||
|
});
|
||||||
|
reject({
|
||||||
|
code: 'LOCATION_AUTH_FAIL',
|
||||||
|
errMsg: authErr.errorMessage || 'authorize location fail'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 已授权,直接获取定位
|
||||||
|
doGetLocation();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.warn('获取授权设置失败,直接尝试定位:', err);
|
||||||
|
// 支付宝小程序使用 my.getLocation,不支持 type 参数
|
||||||
|
my.getLocation({
|
||||||
|
success: (res) => {
|
||||||
|
// 支付宝小程序返回的经纬度可能是字符串,需要先转换为数字
|
||||||
|
const longitude = parseFloat(Number(res.longitude).toFixed(5));
|
||||||
|
const latitude = parseFloat(Number(res.latitude).toFixed(5));
|
||||||
|
console.log('支付宝地址获取成功');
|
||||||
|
resolve({
|
||||||
|
longitude,
|
||||||
|
latitude
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: (error) => {
|
||||||
|
console.error('获取位置失败:', error);
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// 其他非微信、非支付宝小程序平台
|
||||||
// #ifndef MP-WEIXIN
|
// #ifndef MP-WEIXIN
|
||||||
|
// #ifndef MP-ALIPAY
|
||||||
uni.getLocation({
|
uni.getLocation({
|
||||||
type: 'gcj02',
|
type: 'gcj02',
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
const longitude = parseFloat(res.longitude.toFixed(5));
|
// 确保经纬度是数字类型
|
||||||
const latitude = parseFloat(res.latitude.toFixed(5));
|
const longitude = parseFloat(Number(res.longitude).toFixed(5));
|
||||||
|
const latitude = parseFloat(Number(res.latitude).toFixed(5));
|
||||||
console.log('地址获取成功');
|
console.log('地址获取成功');
|
||||||
resolve({
|
resolve({
|
||||||
longitude,
|
longitude,
|
||||||
@@ -569,12 +1003,46 @@ function getUserLocation() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// #endif
|
// #endif
|
||||||
|
// #endif
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 逆地理编码 - 根据经纬度获取地址信息
|
// 逆地理编码 - 根据经纬度获取地址信息
|
||||||
function getRegeo(longitude, latitude) {
|
function getRegeo(longitude, latitude) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
// 支付宝端使用高德逆地理编码
|
||||||
|
if (isAlipayEnv) {
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const gcj = await convertToGcj02(longitude, latitude);
|
||||||
|
const data = await requestAmap('/geocode/regeo', {
|
||||||
|
location: `${gcj.longitude},${gcj.latitude}`,
|
||||||
|
extensions: 'all',
|
||||||
|
batch: 'false'
|
||||||
|
});
|
||||||
|
const info = data.regeocode || {};
|
||||||
|
const comp = info.addressComponent || {};
|
||||||
|
resolve({
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
formatted_address: info.formatted_address || '',
|
||||||
|
addressComponent: {
|
||||||
|
city: comp.city || comp.province || '',
|
||||||
|
district: comp.district || '',
|
||||||
|
province: comp.province || '',
|
||||||
|
street: comp.streetNumber?.street || comp.street || '',
|
||||||
|
street_number: comp.streetNumber?.number || comp.streetNumber?.street_number || ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('高德逆地理编码失败:', error);
|
||||||
|
reject({ success: false, message: error.message || '逆地理编码失败' });
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const qqmap = getQQMapInstance();
|
const qqmap = getQQMapInstance();
|
||||||
if (!qqmap) {
|
if (!qqmap) {
|
||||||
reject({ success: false, message: '腾讯地图SDK未初始化' });
|
reject({ success: false, message: '腾讯地图SDK未初始化' });
|
||||||
@@ -614,6 +1082,45 @@ function getRegeo(longitude, latitude) {
|
|||||||
// 搜索周边POI
|
// 搜索周边POI
|
||||||
function getPoiAround(longitude, latitude, keyword = '', radius = 1000) {
|
function getPoiAround(longitude, latitude, keyword = '', radius = 1000) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
// 支付宝端使用高德周边搜索
|
||||||
|
if (isAlipayEnv) {
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const gcj = await convertToGcj02(longitude, latitude);
|
||||||
|
const data = await requestAmap('/place/around', {
|
||||||
|
location: `${gcj.longitude},${gcj.latitude}`,
|
||||||
|
keywords: keyword,
|
||||||
|
radius,
|
||||||
|
offset: 20,
|
||||||
|
page: 1,
|
||||||
|
extensions: 'base',
|
||||||
|
sortrule: 'distance'
|
||||||
|
});
|
||||||
|
const pois = data.pois || [];
|
||||||
|
const normalized = pois.map((item, idx) => ({
|
||||||
|
id: item.id || idx + 1,
|
||||||
|
title: item.name || '',
|
||||||
|
latitude: Number(item.location?.split(',')[1] || item.location?.lat || 0),
|
||||||
|
longitude: Number(item.location?.split(',')[0] || item.location?.lng || 0),
|
||||||
|
address: item.address || '',
|
||||||
|
category: item.type || '',
|
||||||
|
tel: item.tel || '',
|
||||||
|
city: item.cityname || '',
|
||||||
|
district: item.adname || '',
|
||||||
|
province: item.pname || ''
|
||||||
|
}));
|
||||||
|
resolve({
|
||||||
|
success: true,
|
||||||
|
data: normalized
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('高德周边搜索失败:', error);
|
||||||
|
reject({ success: false, message: error.message || '搜索POI失败' });
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const qqmap = getQQMapInstance();
|
const qqmap = getQQMapInstance();
|
||||||
if (!qqmap) {
|
if (!qqmap) {
|
||||||
reject({ success: false, message: '腾讯地图SDK未初始化' });
|
reject({ success: false, message: '腾讯地图SDK未初始化' });
|
||||||
@@ -645,6 +1152,63 @@ function getPoiAround(longitude, latitude, keyword = '', radius = 1000) {
|
|||||||
// 计算距离(异步)
|
// 计算距离(异步)
|
||||||
function calculateDistance(from, to) {
|
function calculateDistance(from, to) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
// 支付宝端使用高德距离测量接口
|
||||||
|
if (isAlipayEnv) {
|
||||||
|
// to 支持数组
|
||||||
|
const targets = Array.isArray(to) ? to : [to];
|
||||||
|
if (!targets.length) {
|
||||||
|
reject({ success: false, message: '缺少目标坐标' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const doRequest = async (originPoint) => {
|
||||||
|
if (!originPoint || originPoint.longitude === undefined || originPoint.latitude === undefined) {
|
||||||
|
reject({ success: false, message: '缺少起点坐标' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const originGcj = await convertToGcj02(originPoint.longitude || originPoint.lng, originPoint.latitude || originPoint.lat);
|
||||||
|
const convertedTargets = await Promise.all(targets.map(async (item) => {
|
||||||
|
const lng = item.longitude || item.lng;
|
||||||
|
const lat = item.latitude || item.lat;
|
||||||
|
const res = await convertToGcj02(lng, lat);
|
||||||
|
return `${res.longitude},${res.latitude}`;
|
||||||
|
}));
|
||||||
|
const origins = convertedTargets.join('|');
|
||||||
|
const destination = `${originGcj.longitude},${originGcj.latitude}`;
|
||||||
|
const data = await requestAmap('/distance', {
|
||||||
|
origins,
|
||||||
|
destination,
|
||||||
|
type: 3 // 3:步行距离
|
||||||
|
});
|
||||||
|
const results = data.results || [];
|
||||||
|
const distance = results.map(r => Number(r.distance || 0));
|
||||||
|
resolve({
|
||||||
|
success: true,
|
||||||
|
data: distance
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('高德距离计算失败:', error);
|
||||||
|
reject({ success: false, message: error.message || '计算距离失败' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (from && typeof from === 'object') {
|
||||||
|
doRequest(from);
|
||||||
|
} else {
|
||||||
|
// 未传入起点时,使用用户当前定位
|
||||||
|
getUserLocation().then(loc => {
|
||||||
|
doRequest({
|
||||||
|
longitude: loc.longitude,
|
||||||
|
latitude: loc.latitude
|
||||||
|
});
|
||||||
|
}).catch(err => {
|
||||||
|
reject({ success: false, message: err.message || '获取起点位置失败' });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const qqmap = getQQMapInstance();
|
const qqmap = getQQMapInstance();
|
||||||
if (!qqmap) {
|
if (!qqmap) {
|
||||||
reject({ success: false, message: '腾讯地图SDK未初始化' });
|
reject({ success: false, message: '腾讯地图SDK未初始化' });
|
||||||
@@ -685,6 +1249,37 @@ function calculateDistanceSync(lat1, lng1, lat2, lng2) {
|
|||||||
// 关键词提示
|
// 关键词提示
|
||||||
function getSuggestion(keyword, region = '全国') {
|
function getSuggestion(keyword, region = '全国') {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
// 支付宝端使用高德输入提示
|
||||||
|
if (isAlipayEnv) {
|
||||||
|
requestAmap('/assistant/inputtips', {
|
||||||
|
keywords: keyword,
|
||||||
|
city: region === '全国' ? undefined : region,
|
||||||
|
datatype: 'all'
|
||||||
|
}).then((data) => {
|
||||||
|
const tips = data.tips || [];
|
||||||
|
const normalized = tips.map((item, idx) => ({
|
||||||
|
id: item.id || idx + 1,
|
||||||
|
title: item.name || '',
|
||||||
|
adcode: item.adcode || '',
|
||||||
|
address: item.address || '',
|
||||||
|
category: item.type || '',
|
||||||
|
city: item.city || '',
|
||||||
|
district: item.district || '',
|
||||||
|
latitude: item.location ? Number(item.location.split(',')[1]) : null,
|
||||||
|
longitude: item.location ? Number(item.location.split(',')[0]) : null,
|
||||||
|
province: item.province || ''
|
||||||
|
}));
|
||||||
|
resolve({
|
||||||
|
success: true,
|
||||||
|
data: normalized
|
||||||
|
});
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error('高德关键词提示失败:', error);
|
||||||
|
reject({ success: false, message: error.message || '关键词提示失败' });
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const qqmap = getQQMapInstance();
|
const qqmap = getQQMapInstance();
|
||||||
if (!qqmap) {
|
if (!qqmap) {
|
||||||
reject({ success: false, message: '腾讯地图SDK未初始化' });
|
reject({ success: false, message: '腾讯地图SDK未初始化' });
|
||||||
|
|||||||
+20
-11
@@ -248,17 +248,26 @@ class OrderMonitor {
|
|||||||
// 导出单例实例
|
// 导出单例实例
|
||||||
export const orderMonitor = new OrderMonitor()
|
export const orderMonitor = new OrderMonitor()
|
||||||
|
|
||||||
// 监听页面切换事件
|
// 监听页面切换事件(仅微信小程序支持)
|
||||||
uni.onAppRoute((route) => {
|
// #ifdef MP-WEIXIN
|
||||||
const pagePath = route.path || ''
|
if (typeof uni.onAppRoute === 'function') {
|
||||||
const pageSegments = pagePath.split('/')
|
uni.onAppRoute((route) => {
|
||||||
const pageName = pageSegments[pageSegments.length - 1]
|
const pagePath = route.path || ''
|
||||||
|
const pageSegments = pagePath.split('/')
|
||||||
// 设置当前活跃页面
|
const pageName = pageSegments[pageSegments.length - 1]
|
||||||
orderMonitor.setActivePage(pageName || null)
|
|
||||||
|
// 设置当前活跃页面
|
||||||
console.log('页面切换:', pagePath, '当前活跃页面:', pageName)
|
orderMonitor.setActivePage(pageName || null)
|
||||||
})
|
|
||||||
|
console.log('页面切换:', pagePath, '当前活跃页面:', pageName)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef MP-ALIPAY
|
||||||
|
// 支付宝小程序不支持 onAppRoute,通过页面生命周期手动设置
|
||||||
|
// 各个页面需要在 onShow 中调用 orderMonitor.setActivePage()
|
||||||
|
// #endif
|
||||||
|
|
||||||
// 页面加载时自动恢复监控上次的活跃订单(如果有)
|
// 页面加载时自动恢复监控上次的活跃订单(如果有)
|
||||||
const initOrderMonitor = () => {
|
const initOrderMonitor = () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user