This commit is contained in:
2026-07-30 13:07:50 +08:00
parent 0eb2835215
commit 2aae14a627
3 changed files with 88 additions and 15 deletions
+73 -4
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"net/url"
"strings"
"time"
"pointly-tel/amap/model/dto"
@@ -92,22 +93,34 @@ func (s *poiService) searchText(ctx context.Context, apiKey string, req *dto.Sea
const baseUrl = "https://restapi.amap.com/v3/place/text"
needTotal := page * offset
all := make([]*dto.PoiItem, 0, needTotal)
var noPhone []*amapPoi
for ap := 1; ap <= maxPage; ap++ {
if ap > 1 {
time.Sleep(80 * time.Millisecond)
}
pois, _, err := s.fetchTextPage(ctx, apiKey, baseUrl, req.Keywords, req.City, ap, offset)
if err != nil || len(pois) == 0 {
break
}
for _, p := range pois {
if string(p.Tel) == "" {
noPhone = append(noPhone, p)
continue
}
all = append(all, s.toPoiItem(p))
}
if len(all) >= needTotal || len(pois) < offset {
if len(pois) < offset {
break
}
}
// 兜底:对无电话POI按名称搜索,尝试找到电话
if len(all) < needTotal {
extra := s.fallbackPhone(ctx, apiKey, noPhone, req.City, "")
all = append(all, extra...)
}
return s.buildResult(all, page, offset), nil
}
@@ -125,22 +138,34 @@ func (s *poiService) searchAround(ctx context.Context, apiKey string, req *dto.S
locStr := fmt.Sprintf("%.6f,%.6f", req.Longitude, req.Latitude)
needTotal := page * offset
all := make([]*dto.PoiItem, 0, needTotal)
var noPhone []*amapPoi
for ap := 1; ap <= maxPage; ap++ {
if ap > 1 {
time.Sleep(80 * time.Millisecond)
}
pois, _, err := s.fetchAroundPage(ctx, apiKey, baseUrl, req.Keywords, locStr, radius, ap, offset)
if err != nil || len(pois) == 0 {
break
}
for _, p := range pois {
if string(p.Tel) == "" {
noPhone = append(noPhone, p)
continue
}
all = append(all, s.toPoiItem(p))
}
if len(all) >= needTotal || len(pois) < offset {
if len(pois) < offset {
break
}
}
// 兜底:对无电话POI按名称搜索
if len(all) < needTotal {
extra := s.fallbackPhone(ctx, apiKey, noPhone, "", locStr)
all = append(all, extra...)
}
return s.buildResult(all, page, offset), nil
}
@@ -196,6 +221,46 @@ func (s *poiService) buildResult(all []*dto.PoiItem, page, offset int) *dto.Sear
}
}
// fallbackPhone 对无电话POI按名称搜索电话(最多查10个,间隔200ms避免限流)
func (s *poiService) fallbackPhone(ctx context.Context, apiKey string, noPhone []*amapPoi, city, location string) []*dto.PoiItem {
const baseUrl = "https://restapi.amap.com/v3/place/text"
const maxSearch = 50
var found []*dto.PoiItem
seen := map[string]bool{}
for i, np := range noPhone {
if np.Name == "" || i >= maxSearch {
continue
}
if i > 0 {
time.Sleep(100 * time.Millisecond)
}
pois, _, err := s.fetchTextPage(ctx, apiKey, baseUrl, np.Name, city, 1, 10)
if err != nil || len(pois) == 0 {
continue
}
for _, p := range pois {
if string(p.Tel) == "" {
continue
}
if !strings.Contains(p.Name, np.Name) && !strings.Contains(np.Name, p.Name) {
continue
}
if seen[p.Id] {
continue
}
seen[p.Id] = true
found = append(found, s.toPoiItem(p))
g.Log().Info(ctx, "电话补全", "商户", np.Name, "电话", string(p.Tel))
break
}
}
return found
}
// fetchTextPage 文本搜索单页
func (s *poiService) fetchTextPage(ctx context.Context, apiKey, baseUrl, keywords, city string, page, offset int) ([]*amapPoi, int, error) {
pois, total := s.fetchAmapPage(ctx, apiKey, baseUrl, keywords, city, page, offset)
@@ -222,8 +287,10 @@ func (s *poiService) fetchAroundPage(ctx context.Context, apiKey, baseUrl, keywo
}
defer response.Close()
bodyBytes := response.ReadAll()
var amapResp amapResponse
if err := json.Unmarshal(response.ReadAll(), &amapResp); err != nil {
if err := json.Unmarshal(bodyBytes, &amapResp); err != nil {
g.Log().Warning(ctx, "高德API响应解析失败", "error", err)
return nil, 0, err
}
@@ -257,8 +324,10 @@ func (s *poiService) fetchAmapPage(ctx context.Context, apiKey, baseUrl, keyword
}
defer response.Close()
bodyBytes := response.ReadAll()
var amapResp amapResponse
if err := json.Unmarshal(response.ReadAll(), &amapResp); err != nil {
if err := json.Unmarshal(bodyBytes, &amapResp); err != nil {
g.Log().Warning(ctx, "高德API响应解析失败", "error", err)
return nil, 0
}
+7 -1
View File
@@ -270,7 +270,13 @@ watch(city, (val, oldVal) => {
centerLat.value = 0
centerLng.value = 0
mapRef.value.clearRadiusCircle()
mapRef.value.flyTo(coord[0], coord[1], 12)
})
// 范围变更时只重绘圆圈大小,不改变地图视角
watch(radius, (val) => {
if (centerLng.value && centerLat.value && mapRef.value) {
mapRef.value.updateRadiusCircle(val)
}
})
async function doSearch() {
+8 -10
View File
@@ -57,7 +57,6 @@ function addMarkers(pois) {
clearMarkers()
if (!map || !pois.length) return
const bounds = L.latLngBounds()
const pinIcon = L.divIcon({
className: '',
html: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 42" width="32" height="42">
@@ -92,12 +91,6 @@ function addMarkers(pois) {
bounds.extend([lat, lng])
})
// 自动调整视野
if (pois.length === 1) {
map.setView(bounds.getCenter(), 15)
} else {
map.fitBounds(bounds, { padding: [40, 40], maxZoom: 16 })
}
}
function focusMarker(poi) {
@@ -105,7 +98,6 @@ function focusMarker(poi) {
const lng = parseFloat(poi.longitude)
if (isNaN(lat) || isNaN(lng)) return
map.setView([lat, lng], 16)
for (const marker of currentMarkers) {
const pos = marker.getLatLng()
if (Math.abs(pos.lat - lat) < 0.001 && Math.abs(pos.lng - lng) < 0.001) {
@@ -133,7 +125,6 @@ function drawRadiusCircle(lat, lng, radiusMeters) {
weight: 2,
dashArray: '6, 6',
}).addTo(map)
map.fitBounds(radiusCircle.getBounds(), { padding: [40, 40] })
}
function clearRadiusCircle() {
@@ -143,7 +134,14 @@ function clearRadiusCircle() {
}
}
defineExpose({ addMarkers, clearMarkers, focusMarker, drawRadiusCircle, clearRadiusCircle, flyTo })
// 只更新已有圆圈的大小,不改变地图视角
function updateRadiusCircle(radiusMeters) {
if (radiusCircle) {
radiusCircle.setRadius(radiusMeters)
}
}
defineExpose({ addMarkers, clearMarkers, focusMarker, drawRadiusCircle, clearRadiusCircle, updateRadiusCircle, flyTo })
</script>
<style scoped>