You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
6.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;