小程序优化,商铺定位等
This commit is contained in:
@@ -10,6 +10,12 @@ export type ReverseGeocodeResult = {
|
||||
logId: bigint;
|
||||
};
|
||||
|
||||
export type GeocodeAddressResult = {
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
logId: bigint;
|
||||
};
|
||||
|
||||
function normalizeCityName(name: string) {
|
||||
return name.replace(/市$/, '').trim();
|
||||
}
|
||||
@@ -25,6 +31,83 @@ export class TencentLbsProvider {
|
||||
return !!this.config.tencentLbsKey;
|
||||
}
|
||||
|
||||
/** 地址 → 坐标(正向地理编码) */
|
||||
async geocodeAddress(
|
||||
address: string,
|
||||
actorRef?: WechatActorRef,
|
||||
): Promise<GeocodeAddressResult | null> {
|
||||
const trimmed = address.replace(/\s+/g, '').trim();
|
||||
const baseLog = {
|
||||
provider: 'WECHAT_MAP' as const,
|
||||
scene: 'GEOCODE',
|
||||
refType: actorRef?.refType,
|
||||
refId: actorRef?.refId,
|
||||
requestUrl: 'https://apis.map.qq.com/ws/geocoder/v1/',
|
||||
requestBody: { address: trimmed.slice(0, 200) },
|
||||
};
|
||||
|
||||
if (!trimmed) return null;
|
||||
|
||||
if (!this.isEnabled()) {
|
||||
await this.prisma.logThirdParty.create({
|
||||
data: {
|
||||
...baseLog,
|
||||
status: 'FAILED',
|
||||
errorMessage: 'TENCENT_LBS_KEY 未配置',
|
||||
},
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
const url = new URL('https://apis.map.qq.com/ws/geocoder/v1/');
|
||||
url.searchParams.set('address', trimmed);
|
||||
url.searchParams.set('key', this.config.tencentLbsKey);
|
||||
|
||||
try {
|
||||
const res = await fetch(url.toString());
|
||||
const data = (await res.json()) as {
|
||||
status?: number;
|
||||
message?: string;
|
||||
result?: { location?: { lat?: number; lng?: number } };
|
||||
};
|
||||
const loc = data.result?.location;
|
||||
const ok =
|
||||
data.status === 0 &&
|
||||
typeof loc?.lat === 'number' &&
|
||||
typeof loc?.lng === 'number' &&
|
||||
Number.isFinite(loc.lat) &&
|
||||
Number.isFinite(loc.lng);
|
||||
|
||||
const log = await this.prisma.logThirdParty.create({
|
||||
data: {
|
||||
...baseLog,
|
||||
responseBody: {
|
||||
status: data.status,
|
||||
message: data.message,
|
||||
lat: loc?.lat,
|
||||
lng: loc?.lng,
|
||||
},
|
||||
status: ok ? 'SUCCESS' : 'FAILED',
|
||||
errorMessage: ok ? undefined : data.message ?? '地理编码失败',
|
||||
},
|
||||
});
|
||||
|
||||
if (!ok || !loc) return null;
|
||||
return { latitude: loc.lat!, longitude: loc.lng!, logId: log.id };
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
this.logger.error(`Tencent LBS geocode failed: ${message}`);
|
||||
await this.prisma.logThirdParty.create({
|
||||
data: {
|
||||
...baseLog,
|
||||
status: 'FAILED',
|
||||
errorMessage: message.slice(0, 512),
|
||||
},
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async reverseGeocode(
|
||||
latitude: number,
|
||||
longitude: number,
|
||||
|
||||
Reference in New Issue
Block a user