fix(admin,partner): harden Tencent locpicker coords and confirm flow
CI / verify (pull_request) Has been cancelled
CI / verify (pull_request) Has been cancelled
Accept latlng-only postMessage, confirm before apply, and read LBS key per request. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import { Modal, Spin, Typography, message } from 'antd';
|
import { Button, Modal, Space, Spin, Typography, message } from 'antd';
|
||||||
import type { ClientRuntimeConfig } from '@dukang/shared-types';
|
import type { ClientRuntimeConfig } from '@dukang/shared-types';
|
||||||
import { request } from '../lib/api';
|
import { request } from '../lib/api';
|
||||||
import {
|
import {
|
||||||
@@ -39,9 +39,13 @@ export default function TencentLocPickerModal({
|
|||||||
const [key, setKey] = useState<string | null>(cachedKey ?? null);
|
const [key, setKey] = useState<string | null>(cachedKey ?? null);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
|
const [pending, setPending] = useState<TencentPickedLocation | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!open) return;
|
if (!open) {
|
||||||
|
setPending(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
setError('');
|
setError('');
|
||||||
if (key) return;
|
if (key) return;
|
||||||
@@ -70,30 +74,56 @@ export default function TencentLocPickerModal({
|
|||||||
function onMessage(event: MessageEvent) {
|
function onMessage(event: MessageEvent) {
|
||||||
const picked = parseTencentLocPickerMessage(event.data);
|
const picked = parseTencentLocPickerMessage(event.data);
|
||||||
if (!picked) return;
|
if (!picked) return;
|
||||||
onPick(picked);
|
setPending(picked);
|
||||||
onClose();
|
|
||||||
}
|
}
|
||||||
window.addEventListener('message', onMessage);
|
window.addEventListener('message', onMessage);
|
||||||
return () => window.removeEventListener('message', onMessage);
|
return () => window.removeEventListener('message', onMessage);
|
||||||
}, [open, onPick, onClose]);
|
}, [open]);
|
||||||
|
|
||||||
const src = useMemo(() => {
|
const src = useMemo(() => {
|
||||||
if (!key) return '';
|
if (!key) return '';
|
||||||
|
const lat = latitude != null ? Number(latitude) : undefined;
|
||||||
|
const lng = longitude != null ? Number(longitude) : undefined;
|
||||||
return buildTencentLocPickerUrl(key, {
|
return buildTencentLocPickerUrl(key, {
|
||||||
latitude: latitude != null ? Number(latitude) : undefined,
|
latitude: lat != null && Number.isFinite(lat) ? lat : undefined,
|
||||||
longitude: longitude != null ? Number(longitude) : undefined,
|
longitude: lng != null && Number.isFinite(lng) ? lng : undefined,
|
||||||
});
|
});
|
||||||
}, [key, latitude, longitude]);
|
}, [key, latitude, longitude]);
|
||||||
|
|
||||||
|
function confirmPick() {
|
||||||
|
if (!pending) {
|
||||||
|
message.warning('请先在地图上选择或搜索一个位置');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onPick(pending);
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title="腾讯地图选点"
|
title="腾讯地图选点"
|
||||||
open={open}
|
open={open}
|
||||||
onCancel={onClose}
|
onCancel={onClose}
|
||||||
footer={null}
|
|
||||||
width={720}
|
width={720}
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
styles={{ body: { padding: 0, height: 560 } }}
|
styles={{ body: { padding: 0, height: 560 } }}
|
||||||
|
footer={
|
||||||
|
<Space style={{ width: '100%', justifyContent: 'space-between' }}>
|
||||||
|
<Typography.Text type="secondary" style={{ maxWidth: 420 }} ellipsis>
|
||||||
|
{pending
|
||||||
|
? `${pending.latitude.toFixed(6)}, ${pending.longitude.toFixed(6)}${
|
||||||
|
pending.name ? ` · ${pending.name}` : ''
|
||||||
|
}`
|
||||||
|
: '在地图中点选 / 搜索后,点击确认选点'}
|
||||||
|
</Typography.Text>
|
||||||
|
<Space>
|
||||||
|
<Button onClick={onClose}>取消</Button>
|
||||||
|
<Button type="primary" disabled={!pending} onClick={confirmPick}>
|
||||||
|
确认选点
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div style={{ height: 560, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
<div style={{ height: 560, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||||||
@@ -102,11 +132,16 @@ export default function TencentLocPickerModal({
|
|||||||
) : error ? (
|
) : error ? (
|
||||||
<div style={{ padding: 24 }}>
|
<div style={{ padding: 24 }}>
|
||||||
<Typography.Text type="danger">{error}</Typography.Text>
|
<Typography.Text type="danger">{error}</Typography.Text>
|
||||||
|
<Typography.Paragraph type="secondary" style={{ marginTop: 12, marginBottom: 0 }}>
|
||||||
|
若地图能开但看不到附近地点列表,请在腾讯位置服务控制台为该 Key 开启
|
||||||
|
WebServiceAPI,并将白名单域名加入 apis.map.qq.com。
|
||||||
|
</Typography.Paragraph>
|
||||||
</div>
|
</div>
|
||||||
) : src ? (
|
) : src ? (
|
||||||
<iframe
|
<iframe
|
||||||
title="腾讯地图选点"
|
title="腾讯地图选点"
|
||||||
src={src}
|
src={src}
|
||||||
|
allow="geolocation *"
|
||||||
style={{ width: '100%', height: 560, border: 0, display: 'block' }}
|
style={{ width: '100%', height: 560, border: 0, display: 'block' }}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@@ -14,7 +14,22 @@ type LocPickerMessage = {
|
|||||||
cityname?: string;
|
cityname?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const REFERER = 'dukang-haoke';
|
const REFERER = 'dukang';
|
||||||
|
|
||||||
|
function coerceMessageData(data: unknown): LocPickerMessage | null {
|
||||||
|
if (data == null) return null;
|
||||||
|
if (typeof data === 'string') {
|
||||||
|
const trimmed = data.trim();
|
||||||
|
if (!trimmed || (trimmed[0] !== '{' && trimmed[0] !== '[')) return null;
|
||||||
|
try {
|
||||||
|
return JSON.parse(trimmed) as LocPickerMessage;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof data === 'object') return data as LocPickerMessage;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
export function buildTencentLocPickerUrl(
|
export function buildTencentLocPickerUrl(
|
||||||
key: string,
|
key: string,
|
||||||
@@ -26,6 +41,8 @@ export function buildTencentLocPickerUrl(
|
|||||||
key,
|
key,
|
||||||
referer: REFERER,
|
referer: REFERER,
|
||||||
policy: '1',
|
policy: '1',
|
||||||
|
total: '20',
|
||||||
|
radius: '2000',
|
||||||
});
|
});
|
||||||
const lat = options?.latitude;
|
const lat = options?.latitude;
|
||||||
const lng = options?.longitude;
|
const lng = options?.longitude;
|
||||||
@@ -43,18 +60,21 @@ export function buildTencentLocPickerUrl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function parseTencentLocPickerMessage(data: unknown): TencentPickedLocation | null {
|
export function parseTencentLocPickerMessage(data: unknown): TencentPickedLocation | null {
|
||||||
const loc = data as LocPickerMessage;
|
const loc = coerceMessageData(data);
|
||||||
if (!loc || loc.module !== 'locationPicker') return null;
|
if (!loc || loc.module !== 'locationPicker') return null;
|
||||||
const lat = Number(loc.latlng?.lat);
|
const lat = Number(loc.latlng?.lat);
|
||||||
const lng = Number(loc.latlng?.lng);
|
const lng = Number(loc.latlng?.lng);
|
||||||
if (!Number.isFinite(lat) || !Number.isFinite(lng)) return null;
|
if (!Number.isFinite(lat) || !Number.isFinite(lng)) return null;
|
||||||
// 列表滑动过程中偶发空 POI,忽略无名称且无地址的噪声
|
|
||||||
if (!loc.poiname && !loc.poiaddress) return null;
|
let name = loc.poiname?.trim() || undefined;
|
||||||
|
const address = loc.poiaddress?.trim() || undefined;
|
||||||
|
if (name === '我的位置' && address) name = address;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
latitude: lat,
|
latitude: lat,
|
||||||
longitude: lng,
|
longitude: lng,
|
||||||
address: loc.poiaddress?.trim() || undefined,
|
address,
|
||||||
name: loc.poiname?.trim() || undefined,
|
name,
|
||||||
cityname: loc.cityname?.trim() || undefined,
|
cityname: loc.cityname?.trim() || undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,9 +40,13 @@ export default function TencentLocPickerOverlay({
|
|||||||
const [key, setKey] = useState<string | null>(cachedKey ?? null);
|
const [key, setKey] = useState<string | null>(cachedKey ?? null);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
|
const [pending, setPending] = useState<TencentPickedLocation | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!open) return;
|
if (!open) {
|
||||||
|
setPending(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
setError('');
|
setError('');
|
||||||
if (key) return;
|
if (key) return;
|
||||||
@@ -67,23 +71,30 @@ export default function TencentLocPickerOverlay({
|
|||||||
function onMessage(event: MessageEvent) {
|
function onMessage(event: MessageEvent) {
|
||||||
const picked = parseTencentLocPickerMessage(event.data);
|
const picked = parseTencentLocPickerMessage(event.data);
|
||||||
if (!picked) return;
|
if (!picked) return;
|
||||||
onPick(picked);
|
setPending(picked);
|
||||||
onClose();
|
|
||||||
}
|
}
|
||||||
window.addEventListener('message', onMessage);
|
window.addEventListener('message', onMessage);
|
||||||
return () => window.removeEventListener('message', onMessage);
|
return () => window.removeEventListener('message', onMessage);
|
||||||
}, [open, onPick, onClose]);
|
}, [open]);
|
||||||
|
|
||||||
const src = useMemo(() => {
|
const src = useMemo(() => {
|
||||||
if (!key) return '';
|
if (!key) return '';
|
||||||
|
const lat = latitude != null ? Number(latitude) : undefined;
|
||||||
|
const lng = longitude != null ? Number(longitude) : undefined;
|
||||||
return buildTencentLocPickerUrl(key, {
|
return buildTencentLocPickerUrl(key, {
|
||||||
latitude: latitude != null ? Number(latitude) : undefined,
|
latitude: lat != null && Number.isFinite(lat) ? lat : undefined,
|
||||||
longitude: longitude != null ? Number(longitude) : undefined,
|
longitude: lng != null && Number.isFinite(lng) ? lng : undefined,
|
||||||
});
|
});
|
||||||
}, [key, latitude, longitude]);
|
}, [key, latitude, longitude]);
|
||||||
|
|
||||||
if (!open) return null;
|
if (!open) return null;
|
||||||
|
|
||||||
|
function confirmPick() {
|
||||||
|
if (!pending) return;
|
||||||
|
onPick(pending);
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -109,21 +120,50 @@ export default function TencentLocPickerOverlay({
|
|||||||
关闭
|
关闭
|
||||||
</button>
|
</button>
|
||||||
<span style={{ fontWeight: 600 }}>地图选点</span>
|
<span style={{ fontWeight: 600 }}>地图选点</span>
|
||||||
<span style={{ width: 52 }} />
|
<button
|
||||||
|
type="button"
|
||||||
|
className="partner-btn-primary"
|
||||||
|
style={{ padding: '6px 12px', opacity: pending ? 1 : 0.45, width: 'auto' }}
|
||||||
|
disabled={!pending}
|
||||||
|
onClick={confirmPick}
|
||||||
|
>
|
||||||
|
确认
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{pending ? (
|
||||||
|
<p
|
||||||
|
className="label-md text-muted"
|
||||||
|
style={{
|
||||||
|
margin: 0,
|
||||||
|
padding: '8px 16px',
|
||||||
|
borderBottom: '1px solid rgba(0,0,0,0.04)',
|
||||||
|
flexShrink: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
已选 {pending.latitude.toFixed(6)}, {pending.longitude.toFixed(6)}
|
||||||
|
{pending.name ? ` · ${pending.name}` : ''}
|
||||||
|
</p>
|
||||||
|
) : null}
|
||||||
<div style={{ flex: 1, minHeight: 0, position: 'relative' }}>
|
<div style={{ flex: 1, minHeight: 0, position: 'relative' }}>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<p className="label-md text-muted" style={{ padding: 24, textAlign: 'center' }}>
|
<p className="label-md text-muted" style={{ padding: 24, textAlign: 'center' }}>
|
||||||
加载地图…
|
加载地图…
|
||||||
</p>
|
</p>
|
||||||
) : error ? (
|
) : error ? (
|
||||||
<p className="label-md" style={{ padding: 24, color: 'var(--color-heritage-red, #a61d24)' }}>
|
<div style={{ padding: 24 }}>
|
||||||
|
<p className="label-md" style={{ color: 'var(--color-heritage-red, #a61d24)' }}>
|
||||||
{error}
|
{error}
|
||||||
</p>
|
</p>
|
||||||
|
<p className="label-md text-muted" style={{ marginTop: 12 }}>
|
||||||
|
若地图能开但看不到附近地点列表,请确认 Key 已开启 WebServiceAPI,并白名单
|
||||||
|
apis.map.qq.com。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
) : src ? (
|
) : src ? (
|
||||||
<iframe
|
<iframe
|
||||||
title="腾讯地图选点"
|
title="腾讯地图选点"
|
||||||
src={src}
|
src={src}
|
||||||
|
allow="geolocation *"
|
||||||
style={{ width: '100%', height: '100%', border: 0, display: 'block' }}
|
style={{ width: '100%', height: '100%', border: 0, display: 'block' }}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@@ -14,7 +14,22 @@ type LocPickerMessage = {
|
|||||||
cityname?: string;
|
cityname?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const REFERER = 'dukang-haoke';
|
const REFERER = 'dukang';
|
||||||
|
|
||||||
|
function coerceMessageData(data: unknown): LocPickerMessage | null {
|
||||||
|
if (data == null) return null;
|
||||||
|
if (typeof data === 'string') {
|
||||||
|
const trimmed = data.trim();
|
||||||
|
if (!trimmed || (trimmed[0] !== '{' && trimmed[0] !== '[')) return null;
|
||||||
|
try {
|
||||||
|
return JSON.parse(trimmed) as LocPickerMessage;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof data === 'object') return data as LocPickerMessage;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
export function buildTencentLocPickerUrl(
|
export function buildTencentLocPickerUrl(
|
||||||
key: string,
|
key: string,
|
||||||
@@ -26,6 +41,8 @@ export function buildTencentLocPickerUrl(
|
|||||||
key,
|
key,
|
||||||
referer: REFERER,
|
referer: REFERER,
|
||||||
policy: '1',
|
policy: '1',
|
||||||
|
total: '20',
|
||||||
|
radius: '2000',
|
||||||
});
|
});
|
||||||
const lat = options?.latitude;
|
const lat = options?.latitude;
|
||||||
const lng = options?.longitude;
|
const lng = options?.longitude;
|
||||||
@@ -43,17 +60,21 @@ export function buildTencentLocPickerUrl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function parseTencentLocPickerMessage(data: unknown): TencentPickedLocation | null {
|
export function parseTencentLocPickerMessage(data: unknown): TencentPickedLocation | null {
|
||||||
const loc = data as LocPickerMessage;
|
const loc = coerceMessageData(data);
|
||||||
if (!loc || loc.module !== 'locationPicker') return null;
|
if (!loc || loc.module !== 'locationPicker') return null;
|
||||||
const lat = Number(loc.latlng?.lat);
|
const lat = Number(loc.latlng?.lat);
|
||||||
const lng = Number(loc.latlng?.lng);
|
const lng = Number(loc.latlng?.lng);
|
||||||
if (!Number.isFinite(lat) || !Number.isFinite(lng)) return null;
|
if (!Number.isFinite(lat) || !Number.isFinite(lng)) return null;
|
||||||
if (!loc.poiname && !loc.poiaddress) return null;
|
|
||||||
|
let name = loc.poiname?.trim() || undefined;
|
||||||
|
const address = loc.poiaddress?.trim() || undefined;
|
||||||
|
if (name === '我的位置' && address) name = address;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
latitude: lat,
|
latitude: lat,
|
||||||
longitude: lng,
|
longitude: lng,
|
||||||
address: loc.poiaddress?.trim() || undefined,
|
address,
|
||||||
name: loc.poiname?.trim() || undefined,
|
name,
|
||||||
cityname: loc.cityname?.trim() || undefined,
|
cityname: loc.cityname?.trim() || undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,9 @@ WX_PAY_NOTIFY_URL=https://api.dukanghaoke.com/api/v1/callbacks/wechat/pay
|
|||||||
WECOM_AIBOT_ENABLED=false
|
WECOM_AIBOT_ENABLED=false
|
||||||
|
|
||||||
# 腾讯位置服务(地理编码 / 逆地理 / 地图选点组件)
|
# 腾讯位置服务(地理编码 / 逆地理 / 地图选点组件)
|
||||||
# 地图选点需在控制台为 Key 配置域名白名单,并允许组件域名 apis.map.qq.com
|
# 控制台须:1) 开启 WebServiceAPI(否则选点搜不到附近列表)
|
||||||
|
# 2) WebService 域名白名单加入 apis.map.qq.com
|
||||||
|
# 3) 浏览器 Key 按管理端 / 合伙人 H5 域名限制(可选)
|
||||||
TENCENT_LBS_KEY=
|
TENCENT_LBS_KEY=
|
||||||
|
|
||||||
# 阿里云 OSS(ali-oss@6.x;凭证齐全时直传,缺失则服务端报错)
|
# 阿里云 OSS(ali-oss@6.x;凭证齐全时直传,缺失则服务端报错)
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ export const SYSTEM_CONFIG_FIELDS: SystemConfigFieldMeta[] = [
|
|||||||
{ key: 'OSS_MAX_UPLOAD_BYTES', label: '单文件上限(字节)', group: G.oss, type: 'number', requiresRestart: false },
|
{ key: 'OSS_MAX_UPLOAD_BYTES', label: '单文件上限(字节)', group: G.oss, type: 'number', requiresRestart: false },
|
||||||
|
|
||||||
{ key: 'USER_H5_URL', label: 'C 端 H5 落地页', group: G.app, type: 'string', requiresRestart: false },
|
{ key: 'USER_H5_URL', label: 'C 端 H5 落地页', group: G.app, type: 'string', requiresRestart: false },
|
||||||
{ key: 'TENCENT_LBS_KEY', label: '腾讯位置服务 Key(地理编码 / 地图选点)', group: G.app, type: 'password', secret: true, requiresRestart: false },
|
{ key: 'TENCENT_LBS_KEY', label: '腾讯位置服务 Key(须开 WebServiceAPI;白名单含 apis.map.qq.com)', group: G.app, type: 'password', secret: true, requiresRestart: false },
|
||||||
|
|
||||||
{ key: 'DEPLOY_WEBHOOK_URL', label: '发布 Webhook URL', group: G.deploy, type: 'string', requiresRestart: false },
|
{ key: 'DEPLOY_WEBHOOK_URL', label: '发布 Webhook URL', group: G.deploy, type: 'string', requiresRestart: false },
|
||||||
{ key: 'DEPLOY_WEBHOOK_SECRET', label: '发布 Webhook Secret', group: G.deploy, type: 'password', secret: true, requiresRestart: false },
|
{ key: 'DEPLOY_WEBHOOK_SECRET', label: '发布 Webhook Secret', group: G.deploy, type: 'password', secret: true, requiresRestart: false },
|
||||||
|
|||||||
@@ -23,12 +23,16 @@ function normalizeCityName(name: string) {
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class TencentLbsProvider {
|
export class TencentLbsProvider {
|
||||||
private readonly logger = new Logger(TencentLbsProvider.name);
|
private readonly logger = new Logger(TencentLbsProvider.name);
|
||||||
private readonly config = loadAppConfig();
|
|
||||||
|
|
||||||
constructor(private readonly prisma: PrismaService) {}
|
constructor(private readonly prisma: PrismaService) {}
|
||||||
|
|
||||||
|
/** 每次读取,避免构造时缓存、以及系统设置热更新后仍用旧 Key */
|
||||||
|
private getLbsKey() {
|
||||||
|
return (loadAppConfig().tencentLbsKey || '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
isEnabled() {
|
isEnabled() {
|
||||||
return !!this.config.tencentLbsKey;
|
return !!this.getLbsKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 地址 → 坐标(正向地理编码) */
|
/** 地址 → 坐标(正向地理编码) */
|
||||||
@@ -61,7 +65,7 @@ export class TencentLbsProvider {
|
|||||||
|
|
||||||
const url = new URL('https://apis.map.qq.com/ws/geocoder/v1/');
|
const url = new URL('https://apis.map.qq.com/ws/geocoder/v1/');
|
||||||
url.searchParams.set('address', trimmed);
|
url.searchParams.set('address', trimmed);
|
||||||
url.searchParams.set('key', this.config.tencentLbsKey);
|
url.searchParams.set('key', this.getLbsKey());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch(url.toString());
|
const res = await fetch(url.toString());
|
||||||
@@ -140,7 +144,7 @@ export class TencentLbsProvider {
|
|||||||
const location = `${latitude},${longitude}`;
|
const location = `${latitude},${longitude}`;
|
||||||
const url = new URL('https://apis.map.qq.com/ws/geocoder/v1/');
|
const url = new URL('https://apis.map.qq.com/ws/geocoder/v1/');
|
||||||
url.searchParams.set('location', location);
|
url.searchParams.set('location', location);
|
||||||
url.searchParams.set('key', this.config.tencentLbsKey);
|
url.searchParams.set('key', this.getLbsKey());
|
||||||
url.searchParams.set('get_poi', '0');
|
url.searchParams.set('get_poi', '0');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user