fix:对接高德地图,修复地图bug

This commit is contained in:
2025-12-23 10:39:41 +08:00
parent d12986b85e
commit 76bdcd1aba
20 changed files with 964 additions and 399 deletions
+614 -19
View File
@@ -39,6 +39,287 @@ const getPermissionText = (key) => {
// 腾讯地图Key
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核心代码
const QQMapWX = (function() {
// 错误配置
@@ -118,22 +399,55 @@ const QQMapWX = (function() {
}
};
if (!param.location) {
// 微信小程序使用 wx.getLocation
// #ifdef MP-WEIXIN
wx.getLocation({
type: 'gcj02',
success: locationsuccess,
fail: locationfail,
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)) {
const location = Utils.getLocationParam(param.location);
locationsuccess(location);
}
},
// 构造微信请求参数
// 构造腾讯地图API请求参数(跨平台兼容)
buildWxRequestConfig(param, options, feature) {
const that = this;
options.header = { "content-type": "application/json" };
// GET请求不需要设置content-typeuni.request会自动处理
options.header = options.header || {};
options.method = 'GET';
options.success = function (res) {
const data = res.data;
@@ -280,8 +594,10 @@ const QQMapWX = (function() {
const locationsuccess = function (result) {
requestParam.location = result.latitude + ',' + result.longitude;
wx.request(Utils.buildWxRequestConfig(options, {
url: URL_GET_GEOCODER,
// 调用腾讯地图API - 逆地理编码接口
// 使用 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
}, 'reverseGeocoder'));
};
@@ -323,8 +639,10 @@ const QQMapWX = (function() {
const locationsuccess = function (result) {
requestParam.boundary = "nearby(" + result.latitude + "," + result.longitude + "," + distance + "," + auto_extend + ")";
wx.request(Utils.buildWxRequestConfig(options, {
url: URL_SEARCH,
// 调用腾讯地图API - POI周边检索接口
// 使用 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
}, 'search'));
};
@@ -368,15 +686,19 @@ const QQMapWX = (function() {
if (options.location) {
const locationsuccess = function (result) {
requestParam.location = result.latitude + ',' + result.longitude;
wx.request(Utils.buildWxRequestConfig(options, {
url: URL_SUGGESTION,
// 调用腾讯地图API - 地点搜索建议接口
// 使用 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
}, "suggest"));
};
Utils.locationProcess(options, locationsuccess);
} else {
wx.request(Utils.buildWxRequestConfig(options, {
url: URL_SUGGESTION,
// 调用腾讯地图API - 地点搜索建议接口(无位置信息)
// 使用 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
}, "suggest"));
}
@@ -408,8 +730,10 @@ const QQMapWX = (function() {
const locationsuccess = function (result) {
requestParam.from = result.latitude + ',' + result.longitude;
wx.request(Utils.buildWxRequestConfig(options, {
url: URL_DISTANCE,
// 调用腾讯地图API - 距离计算接口
// 使用 uni.request 跨平台API,在支付宝小程序中自动转换为 my.request
uni.request(Utils.buildWxRequestConfig(options, {
url: URL_DISTANCE, // 腾讯地图API地址:https://apis.map.qq.com/ws/distance/v1/
data: requestParam
}, 'calculateDistance'));
};
@@ -426,6 +750,10 @@ let qqmapInstance = null;
// 初始化腾讯地图SDK
function initQQMap() {
if (isAlipayEnv) {
// 支付宝端改用高德地图服务
return null;
}
if (!qqmapInstance) {
try {
qqmapInstance = new QQMapWX({
@@ -441,6 +769,9 @@ function initQQMap() {
// 获取腾讯地图SDK实例
function getQQMapInstance() {
if (isAlipayEnv) {
return null;
}
return qqmapInstance || initQQMap();
}
@@ -487,8 +818,9 @@ function getUserLocation() {
wx.getLocation({
type: 'gcj02',
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('地址获取成功');
resolve({
longitude,
@@ -533,8 +865,9 @@ function getUserLocation() {
wx.getLocation({
type: 'gcj02',
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('地址获取成功');
resolve({
longitude,
@@ -550,13 +883,114 @@ function getUserLocation() {
});
// #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-ALIPAY
uni.getLocation({
type: 'gcj02',
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('地址获取成功');
resolve({
longitude,
@@ -569,12 +1003,46 @@ function getUserLocation() {
}
});
// #endif
// #endif
});
}
// 逆地理编码 - 根据经纬度获取地址信息
function getRegeo(longitude, latitude) {
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();
if (!qqmap) {
reject({ success: false, message: '腾讯地图SDK未初始化' });
@@ -614,6 +1082,45 @@ function getRegeo(longitude, latitude) {
// 搜索周边POI
function getPoiAround(longitude, latitude, keyword = '', radius = 1000) {
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();
if (!qqmap) {
reject({ success: false, message: '腾讯地图SDK未初始化' });
@@ -645,6 +1152,63 @@ function getPoiAround(longitude, latitude, keyword = '', radius = 1000) {
// 计算距离(异步)
function calculateDistance(from, to) {
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();
if (!qqmap) {
reject({ success: false, message: '腾讯地图SDK未初始化' });
@@ -685,6 +1249,37 @@ function calculateDistanceSync(lat1, lng1, lat2, lng2) {
// 关键词提示
function getSuggestion(keyword, region = '全国') {
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();
if (!qqmap) {
reject({ success: false, message: '腾讯地图SDK未初始化' });
+20 -11
View File
@@ -248,17 +248,26 @@ class OrderMonitor {
// 导出单例实例
export const orderMonitor = new OrderMonitor()
// 监听页面切换事件
uni.onAppRoute((route) => {
const pagePath = route.path || ''
const pageSegments = pagePath.split('/')
const pageName = pageSegments[pageSegments.length - 1]
// 设置当前活跃页面
orderMonitor.setActivePage(pageName || null)
console.log('页面切换:', pagePath, '当前活跃页面:', pageName)
})
// 监听页面切换事件(仅微信小程序支持)
// #ifdef MP-WEIXIN
if (typeof uni.onAppRoute === 'function') {
uni.onAppRoute((route) => {
const pagePath = route.path || ''
const pageSegments = pagePath.split('/')
const pageName = pageSegments[pageSegments.length - 1]
// 设置当前活跃页面
orderMonitor.setActivePage(pageName || null)
console.log('页面切换:', pagePath, '当前活跃页面:', pageName)
})
}
// #endif
// #ifdef MP-ALIPAY
// 支付宝小程序不支持 onAppRoute,通过页面生命周期手动设置
// 各个页面需要在 onShow 中调用 orderMonitor.setActivePage()
// #endif
// 页面加载时自动恢复监控上次的活跃订单(如果有)
const initOrderMonitor = () => {