From 9ed0c24d1179b111ac5ff5d4d1d6adf28935f424 Mon Sep 17 00:00:00 2001 From: jacy <18049821889@163.com> Date: Tue, 28 Jul 2026 00:47:08 +0800 Subject: [PATCH] fix(admin,partner): harden Tencent locpicker coords and confirm flow Accept latlng-only postMessage, confirm before apply, and read LBS key per request. Co-authored-by: Cursor --- .../src/components/TencentLocPickerModal.tsx | 51 +++++++++++++--- apps/admin-web/src/lib/tencentLocPicker.ts | 32 ++++++++-- .../components/TencentLocPickerOverlay.tsx | 60 +++++++++++++++---- apps/h5-partner/src/lib/tencentLocPicker.ts | 31 ++++++++-- server/dukang-api/.env.example | 4 +- .../system-config/system-config.registry.ts | 2 +- .../integrations/map/tencent-lbs.provider.ts | 12 ++-- 7 files changed, 157 insertions(+), 35 deletions(-) diff --git a/apps/admin-web/src/components/TencentLocPickerModal.tsx b/apps/admin-web/src/components/TencentLocPickerModal.tsx index ad05635..f848b5c 100644 --- a/apps/admin-web/src/components/TencentLocPickerModal.tsx +++ b/apps/admin-web/src/components/TencentLocPickerModal.tsx @@ -1,5 +1,5 @@ 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 { request } from '../lib/api'; import { @@ -39,9 +39,13 @@ export default function TencentLocPickerModal({ const [key, setKey] = useState(cachedKey ?? null); const [loading, setLoading] = useState(false); const [error, setError] = useState(''); + const [pending, setPending] = useState(null); useEffect(() => { - if (!open) return; + if (!open) { + setPending(null); + return; + } let cancelled = false; setError(''); if (key) return; @@ -70,30 +74,56 @@ export default function TencentLocPickerModal({ function onMessage(event: MessageEvent) { const picked = parseTencentLocPickerMessage(event.data); if (!picked) return; - onPick(picked); - onClose(); + setPending(picked); } window.addEventListener('message', onMessage); return () => window.removeEventListener('message', onMessage); - }, [open, onPick, onClose]); + }, [open]); const src = useMemo(() => { if (!key) return ''; + const lat = latitude != null ? Number(latitude) : undefined; + const lng = longitude != null ? Number(longitude) : undefined; return buildTencentLocPickerUrl(key, { - latitude: latitude != null ? Number(latitude) : undefined, - longitude: longitude != null ? Number(longitude) : undefined, + latitude: lat != null && Number.isFinite(lat) ? lat : undefined, + longitude: lng != null && Number.isFinite(lng) ? lng : undefined, }); }, [key, latitude, longitude]); + function confirmPick() { + if (!pending) { + message.warning('请先在地图上选择或搜索一个位置'); + return; + } + onPick(pending); + onClose(); + } + return ( + + {pending + ? `${pending.latitude.toFixed(6)}, ${pending.longitude.toFixed(6)}${ + pending.name ? ` · ${pending.name}` : '' + }` + : '在地图中点选 / 搜索后,点击确认选点'} + + + + + + + } > {loading ? (
@@ -102,11 +132,16 @@ export default function TencentLocPickerModal({ ) : error ? (
{error} + + 若地图能开但看不到附近地点列表,请在腾讯位置服务控制台为该 Key 开启 + WebServiceAPI,并将白名单域名加入 apis.map.qq.com。 +
) : src ? (