|
|
const { QQMAP_KEY, QQMAP_REFERER } = require('./config.js');
|
|
|
|
|
|
function formatAddress(comp) {
|
|
|
if (!comp) return '';
|
|
|
const parts = [comp.province, comp.city, comp.district, comp.street, comp.street_number].filter(Boolean);
|
|
|
return parts.join('');
|
|
|
}
|
|
|
|
|
|
function reverseGeocode(point) {
|
|
|
return new Promise((resolve, reject) => {
|
|
|
try {
|
|
|
if (!point || typeof point.latitude !== 'number' || typeof point.longitude !== 'number') {
|
|
|
reject(new Error('Invalid coordinates'));
|
|
|
return;
|
|
|
}
|
|
|
// 先走云函数,失败后总是尝试前端直连;都失败则给出校园语义化兜底
|
|
|
callCloudReverse(point)
|
|
|
.then((addr) => resolve(addr))
|
|
|
.catch(() => {
|
|
|
// 前端直连(需要合法域名;若失败继续兜底)
|
|
|
wx.request({
|
|
|
url: 'https://apis.map.qq.com/ws/geocoder/v1',
|
|
|
method: 'GET',
|
|
|
data: {
|
|
|
location: `${point.latitude},${point.longitude}`,
|
|
|
key: QQMAP_KEY,
|
|
|
get_poi: 1,
|
|
|
poi_options: 'policy=1'
|
|
|
},
|
|
|
success: (res) => {
|
|
|
if (res.statusCode === 200 && res.data && res.data.status === 0 && res.data.result) {
|
|
|
const r = res.data.result;
|
|
|
const addr = (r.formatted_addresses && (r.formatted_addresses.recommend || r.formatted_addresses.rough))
|
|
|
|| r.address
|
|
|
|| (r.address_reference && (r.address_reference.landmark_l2?.title || r.address_reference.landmark?.title))
|
|
|
|| formatAddress(r.address_component);
|
|
|
resolve(addr || '');
|
|
|
} else {
|
|
|
// 最后兜底:根据地标名/校园名构造语义地址
|
|
|
const name = point.landmarkName || point.name || '';
|
|
|
const fallback = name ? `中国民航大学(东丽校区)${name} 附近` : '中国民航大学(东丽校区)校园内附近';
|
|
|
resolve(fallback);
|
|
|
}
|
|
|
},
|
|
|
fail: () => {
|
|
|
const name = point.landmarkName || point.name || '';
|
|
|
const fallback = name ? `中国民航大学(东丽校区)${name} 附近` : '中国民航大学(东丽校区)校园内附近';
|
|
|
resolve(fallback);
|
|
|
}
|
|
|
});
|
|
|
});
|
|
|
} catch (e) {
|
|
|
callCloudReverse(point)
|
|
|
.then((addr) => resolve(addr))
|
|
|
.catch(() => {
|
|
|
const name = point.landmarkName || point.name || '';
|
|
|
const fallback = name ? `中国民航大学(东丽校区)${name} 附近` : '中国民航大学(东丽校区)校园内附近';
|
|
|
resolve(fallback);
|
|
|
});
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
function callCloudReverse(point) {
|
|
|
return new Promise((resolve, reject) => {
|
|
|
try {
|
|
|
wx.cloud.callFunction({
|
|
|
name: 'quickstartFunctions',
|
|
|
data: {
|
|
|
type: 'cloudReverseGeocode',
|
|
|
latitude: point.latitude,
|
|
|
longitude: point.longitude,
|
|
|
// 直接传入前端配置的 QQMAP_KEY,避免云端未配置环境变量时报“缺少QQMAP_KEY”
|
|
|
key: QQMAP_KEY,
|
|
|
referer: QQMAP_REFERER
|
|
|
},
|
|
|
success: (res) => {
|
|
|
try {
|
|
|
if (res.result && res.result.success && res.result.data) {
|
|
|
const r = res.result.data;
|
|
|
const addr = (r.formatted_addresses && (r.formatted_addresses.recommend || r.formatted_addresses.rough))
|
|
|
|| r.address
|
|
|
|| (r.address_reference && (r.address_reference.landmark_l2?.title || r.address_reference.landmark?.title))
|
|
|
|| formatAddress(r.address_component);
|
|
|
resolve(addr || '');
|
|
|
} else {
|
|
|
reject(new Error(res.result?.error || 'Cloud reverse geocode failed'));
|
|
|
}
|
|
|
} catch (e) {
|
|
|
reject(e);
|
|
|
}
|
|
|
},
|
|
|
fail: (err) => {
|
|
|
reject(err);
|
|
|
}
|
|
|
});
|
|
|
} catch (e) {
|
|
|
reject(e);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
module.exports = { reverseGeocode, formatAddress };
|
|
|
|
|
|
/**
|
|
|
* 正向地理编码:根据地址字符串获取坐标
|
|
|
* 返回 { latitude, longitude }
|
|
|
*/
|
|
|
function geocode(address) {
|
|
|
return new Promise((resolve, reject) => {
|
|
|
try {
|
|
|
if (!address || typeof address !== 'string') {
|
|
|
reject(new Error('Invalid address'));
|
|
|
return;
|
|
|
}
|
|
|
// 优先走云函数(支持多 Key 和签名),失败再回退前端直连
|
|
|
wx.cloud.callFunction({
|
|
|
name: 'quickstartFunctions',
|
|
|
data: { type: 'cloudGeocode', address, key: QQMAP_KEY, referer: QQMAP_REFERER },
|
|
|
success: (res) => {
|
|
|
if (res.result && res.result.success && res.result.data) {
|
|
|
resolve(res.result.data);
|
|
|
} else {
|
|
|
// 回退前端直连
|
|
|
wx.request({
|
|
|
url: 'https://apis.map.qq.com/ws/geocoder/v1',
|
|
|
method: 'GET',
|
|
|
data: { address, key: QQMAP_KEY },
|
|
|
success: (resp) => {
|
|
|
if (resp.statusCode === 200 && resp.data && resp.data.status === 0 && resp.data.result && resp.data.result.location) {
|
|
|
const loc = resp.data.result.location;
|
|
|
resolve({ latitude: loc.lat, longitude: loc.lng });
|
|
|
} else {
|
|
|
reject(new Error(resp.data?.message || 'Geocode failed'));
|
|
|
}
|
|
|
},
|
|
|
fail: (e) => reject(e)
|
|
|
});
|
|
|
}
|
|
|
},
|
|
|
fail: () => {
|
|
|
// 云函数不可用时回退前端直连
|
|
|
wx.request({
|
|
|
url: 'https://apis.map.qq.com/ws/geocoder/v1',
|
|
|
method: 'GET',
|
|
|
data: { address, key: QQMAP_KEY },
|
|
|
success: (resp) => {
|
|
|
if (resp.statusCode === 200 && resp.data && resp.data.status === 0 && resp.data.result && resp.data.result.location) {
|
|
|
const loc = resp.data.result.location;
|
|
|
resolve({ latitude: loc.lat, longitude: loc.lng });
|
|
|
} else {
|
|
|
reject(new Error(resp.data?.message || 'Geocode failed'));
|
|
|
}
|
|
|
},
|
|
|
fail: (e) => reject(e)
|
|
|
});
|
|
|
}
|
|
|
});
|
|
|
} catch (e) {
|
|
|
reject(e);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
module.exports.geocode = geocode; |