diff --git a/amap/consts/table_name.go b/amap/consts/table_name.go deleted file mode 100644 index 9403885..0000000 --- a/amap/consts/table_name.go +++ /dev/null @@ -1,5 +0,0 @@ -package consts - -const ( - TableNamePoiMerchant = "poi_merchant" -) diff --git a/amap/dao/poi_dao.go b/amap/dao/poi_dao.go deleted file mode 100644 index 8c2e711..0000000 --- a/amap/dao/poi_dao.go +++ /dev/null @@ -1,63 +0,0 @@ -package dao - -import ( - "context" - "pointly-tel/amap/consts" - "pointly-tel/amap/model/entity" - "pointly-tel/common" - - "github.com/gogf/gf/v2/frame/g" -) - -var PoiMerchant = &poiMerchantDao{} - -type poiMerchantDao struct{} - -func init() { - ctx := context.Background() - _, err := g.DB().Exec(ctx, `CREATE TABLE IF NOT EXISTS `+consts.TableNamePoiMerchant+` ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - poi_id VARCHAR(64) NOT NULL UNIQUE, - name VARCHAR(255) NOT NULL DEFAULT '', - address VARCHAR(500) NOT NULL DEFAULT '', - phone VARCHAR(100) NOT NULL DEFAULT '', - category VARCHAR(255) NOT NULL DEFAULT '', - category_code VARCHAR(64) NOT NULL DEFAULT '', - city VARCHAR(64) NOT NULL DEFAULT '', - city_code VARCHAR(64) NOT NULL DEFAULT '', - longitude REAL DEFAULT 0, - latitude REAL DEFAULT 0, - business_area VARCHAR(255) NOT NULL DEFAULT '', - website VARCHAR(500) NOT NULL DEFAULT '', - raw_data TEXT NOT NULL DEFAULT '', - created_at DATETIME DEFAULT (datetime('now','localtime')), - updated_at DATETIME DEFAULT (datetime('now','localtime')), - deleted_at DATETIME - )`) - if err != nil { - g.Log().Warningf(ctx, "create poi_merchant table failed: %v", err) - } - _, err = g.DB().Exec(ctx, "CREATE INDEX IF NOT EXISTS idx_poi_merchant_poi_id ON "+consts.TableNamePoiMerchant+"(poi_id)") - if err != nil { - g.Log().Warningf(ctx, "create poi_merchant index failed: %v", err) - } -} - -func (d *poiMerchantDao) Insert(ctx context.Context, data *entity.PoiMerchant) (int64, error) { - return common.InsertAndReturnId(ctx, consts.TableNamePoiMerchant, data) -} - -func (d *poiMerchantDao) GetByPoiId(ctx context.Context, poiId string) (*entity.PoiMerchant, error) { - var data *entity.PoiMerchant - err := g.DB().Model(consts.TableNamePoiMerchant).Ctx(ctx).Where("poi_id", poiId).Scan(&data) - return data, err -} - -func (d *poiMerchantDao) GetListByKeywords(ctx context.Context, keywords string) ([]*entity.PoiMerchant, error) { - var list []*entity.PoiMerchant - err := g.DB().Model(consts.TableNamePoiMerchant).Ctx(ctx). - Where("name LIKE ?", "%"+keywords+"%"). - Limit(100). - Scan(&list) - return list, err -} diff --git a/amap/model/dto/poi_dto.go b/amap/model/dto/poi_dto.go index b519fb5..d0a117f 100644 --- a/amap/model/dto/poi_dto.go +++ b/amap/model/dto/poi_dto.go @@ -3,11 +3,14 @@ package dto import "github.com/gogf/gf/v2/frame/g" type SearchPoiReq struct { - g.Meta `path:"/search" method:"get" tags:"POI检索" summary:"POI关键词搜索"` - Keywords string `v:"required" json:"keywords" dc:"搜索关键词"` - City string `json:"city" dc:"城市名称或代码"` - Offset int `d:"20" json:"offset" dc:"每页记录数"` - Page int `d:"1" json:"page" dc:"页码"` + g.Meta `path:"/search" method:"get" tags:"POI检索" summary:"POI搜索"` + Keywords string `json:"keywords" dc:"搜索关键词(周边搜索时选填)"` + City string `json:"city" dc:"城市名称(文本搜索时使用)"` + Longitude float64 `json:"longitude" dc:"中心点经度(周边搜索时使用)"` + Latitude float64 `json:"latitude" dc:"中心点纬度(周边搜索时使用)"` + Radius int `d:"3000" json:"radius" dc:"搜索半径(米,默认3000,最大50000)"` + Offset int `d:"20" json:"offset" dc:"每页记录数"` + Page int `d:"1" json:"page" dc:"页码"` } type PoiItem struct { diff --git a/amap/model/entity/poi.go b/amap/model/entity/poi.go deleted file mode 100644 index aa5545f..0000000 --- a/amap/model/entity/poi.go +++ /dev/null @@ -1,23 +0,0 @@ -package entity - -import "github.com/gogf/gf/v2/os/gtime" - -type PoiMerchant struct { - Id int64 `orm:"id" json:"id" dc:"主键ID"` - PoiId string `orm:"poi_id" json:"poiId" dc:"高德POI ID"` - Name string `orm:"name" json:"name" dc:"商户名称"` - Address string `orm:"address" json:"address" dc:"地址"` - Phone string `orm:"phone" json:"phone" dc:"联系电话"` - Category string `orm:"category" json:"category" dc:"分类"` - CategoryCode string `orm:"category_code" json:"categoryCode" dc:"分类代码"` - City string `orm:"city" json:"city" dc:"城市"` - CityCode string `orm:"city_code" json:"cityCode" dc:"城市代码"` - Longitude float64 `orm:"longitude" json:"longitude" dc:"经度"` - Latitude float64 `orm:"latitude" json:"latitude" dc:"纬度"` - BusinessArea string `orm:"business_area" json:"businessArea" dc:"商圈"` - Website string `orm:"website" json:"website" dc:"网址"` - RawData string `orm:"raw_data" json:"rawData" dc:"原始数据"` - CreatedAt *gtime.Time `orm:"created_at" json:"createdAt" dc:"创建时间"` - UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt" dc:"更新时间"` - DeletedAt *gtime.Time `orm:"deleted_at" json:"deletedAt" dc:"删除时间"` -} diff --git a/amap/service/poi_service.go b/amap/service/poi_service.go index 5eebd3f..4ced67f 100644 --- a/amap/service/poi_service.go +++ b/amap/service/poi_service.go @@ -3,12 +3,11 @@ package service import ( "context" "encoding/json" + "fmt" "net/url" "strings" - "pointly-tel/amap/dao" "pointly-tel/amap/model/dto" - "pointly-tel/amap/model/entity" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" @@ -19,6 +18,11 @@ type poiService struct{} var PoiService = new(poiService) +const ( + maxOffset = 25 // 高德API单页最大条数 + maxPage = 100 // 高德API最大页数 +) + // amapString 处理高德API中字段有时返回string有时返回[]的情况 type amapString string @@ -32,7 +36,6 @@ func (s *amapString) UnmarshalJSON(data []byte) error { return nil } -// Amap API 响应结构 type amapResponse struct { Status string `json:"status"` Info string `json:"info"` @@ -63,18 +66,8 @@ func (s *poiService) Search(ctx context.Context, req *dto.SearchPoiReq) (res *dt if apiKeyVar.IsEmpty() { return nil, gerror.New("请先配置高德地图API Key(config.yml 中的 amap.api_key)") } + apiKey := apiKeyVar.String() - apiUrlVar, _ := g.Cfg().Get(ctx, "amap.api_url") - baseUrl := apiUrlVar.String() - if baseUrl == "" { - baseUrl = "https://restapi.amap.com/v3/place/text" - } - - // 高德POI分页限制:offset 最大 25,page 最大 100 - const ( - maxOffset = 25 - maxPage = 100 - ) offset := req.Offset if offset < 1 { offset = 1 @@ -88,62 +81,109 @@ func (s *poiService) Search(ctx context.Context, req *dto.SearchPoiReq) (res *dt page = maxPage } - params := url.Values{} - params.Set("key", apiKeyVar.String()) - params.Set("keywords", req.Keywords) - params.Set("offset", gconv.String(offset)) - params.Set("page", gconv.String(page)) - params.Set("extensions", "all") - if req.City != "" { - params.Set("city", req.City) + if req.Longitude != 0 && req.Latitude != 0 { + return s.searchAround(ctx, apiKey, req, page, offset) } + return s.searchText(ctx, apiKey, req, page, offset) +} - requestUrl := baseUrl + "?" + params.Encode() - g.Log().Info(ctx, "调用高德POI搜索", "url", requestUrl) +// searchText 文本搜索,实时扫描高德页面,在内存中过滤有电话的POI +func (s *poiService) searchText(ctx context.Context, apiKey string, req *dto.SearchPoiReq, page, offset int) (*dto.SearchPoiRes, error) { + const baseUrl = "https://restapi.amap.com/v3/place/text" + needTotal := page * offset + all := make([]*dto.PoiItem, 0, needTotal) - response, err := g.Client().Get(ctx, requestUrl) - if err != nil { - return nil, gerror.Newf("高德API请求失败: %v", err) - } - defer response.Close() - - var amapResp amapResponse - if err := json.Unmarshal(response.ReadAll(), &amapResp); err != nil { - return nil, gerror.Newf("响应解析失败: %v", err) - } - - if amapResp.Status != "1" { - return nil, gerror.Newf("高德API返回错误: %s", amapResp.Info) - } - - total := gconv.Int(amapResp.Count) - items := make([]*dto.PoiItem, 0, len(amapResp.Pois)) - - for _, p := range amapResp.Pois { - lng, lat := parseLocation(p.Location) - item := &dto.PoiItem{ - PoiId: p.Id, - Name: p.Name, - Address: p.Address, - Phone: string(p.Tel), - Category: p.Type, - City: string(p.City), - Longitude: gconv.String(lng), - Latitude: gconv.String(lat), - BusinessArea: string(p.BusinessArea), - Website: string(p.Website), + for ap := 1; ap <= maxPage; ap++ { + pois, _, err := s.fetchTextPage(ctx, apiKey, baseUrl, req.Keywords, req.City, ap, offset) + if err != nil || len(pois) == 0 { + break } - items = append(items, item) + for _, p := range pois { + if string(p.Tel) == "" { + continue + } + all = append(all, s.toPoiItem(p)) + } + if len(all) >= needTotal || len(pois) < offset { + break + } + } + return s.buildResult(all, page, offset), nil +} - go s.cachePoi(ctx, p) +// searchAround 周边搜索,实时扫描高德页面,在内存中过滤有电话的POI +func (s *poiService) searchAround(ctx context.Context, apiKey string, req *dto.SearchPoiReq, page, offset int) (*dto.SearchPoiRes, error) { + const baseUrl = "https://restapi.amap.com/v3/place/around" + + radius := req.Radius + if radius < 1 { + radius = 1 + } else if radius > 50000 { + radius = 50000 } - // 计算最大可查页数(高德限制最多查 100 页) - maxPageCalculated := maxPage - if total > 0 { - if maxPageCalculated*offset > total { - maxPageCalculated = (total + offset - 1) / offset + locStr := fmt.Sprintf("%.6f,%.6f", req.Longitude, req.Latitude) + needTotal := page * offset + all := make([]*dto.PoiItem, 0, needTotal) + + for ap := 1; ap <= maxPage; ap++ { + 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) == "" { + continue + } + all = append(all, s.toPoiItem(p)) + } + if len(all) >= needTotal || len(pois) < offset { + break + } + } + return s.buildResult(all, page, offset), nil +} + +// toPoiItem 将高德POI原始数据转换为输出DTO +func (s *poiService) toPoiItem(p *amapPoi) *dto.PoiItem { + lng, lat := parseLocation(p.Location) + return &dto.PoiItem{ + PoiId: p.Id, + Name: p.Name, + Address: p.Address, + Phone: string(p.Tel), + Category: p.Type, + City: string(p.City), + Longitude: gconv.String(lng), + Latitude: gconv.String(lat), + BusinessArea: string(p.BusinessArea), + Website: string(p.Website), + } +} + +// buildResult 从内存列表中截取当前页数据 +func (s *poiService) buildResult(all []*dto.PoiItem, page, offset int) *dto.SearchPoiRes { + total := len(all) + maxPageCalc := total / offset + if total%offset != 0 { + maxPageCalc++ + } + if maxPageCalc < 1 { + maxPageCalc = 1 + } + + start := (page - 1) * offset + end := start + offset + if start > total { + start = total + } + if end > total { + end = total + } + + items := all[start:end] + if items == nil { + items = []*dto.PoiItem{} } return &dto.SearchPoiRes{ @@ -152,38 +192,83 @@ func (s *poiService) Search(ctx context.Context, req *dto.SearchPoiReq) (res *dt Count: len(items), Page: page, Offset: offset, - MaxPage: maxPageCalculated, - }, nil + MaxPage: maxPageCalc, + } } -// cachePoi 将POI结果异步缓存到数据库 -func (s *poiService) cachePoi(ctx context.Context, p *amapPoi) { - existing, _ := dao.PoiMerchant.GetByPoiId(ctx, p.Id) - if existing != nil { - return - } +// 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) + return pois, total, nil +} - lng, lat := parseLocation(p.Location) - rawBytes, _ := json.Marshal(p) +// fetchAroundPage 周边搜索单页 +func (s *poiService) fetchAroundPage(ctx context.Context, apiKey, baseUrl, keywords, location string, radius, page, offset int) ([]*amapPoi, int, error) { + params := url.Values{} + params.Set("key", apiKey) + params.Set("keywords", keywords) + params.Set("location", location) + params.Set("radius", gconv.String(radius)) + params.Set("offset", gconv.String(offset)) + params.Set("page", gconv.String(page)) + params.Set("extensions", "all") - _, err := dao.PoiMerchant.Insert(ctx, &entity.PoiMerchant{ - PoiId: p.Id, - Name: p.Name, - Address: p.Address, - Phone: string(p.Tel), - Category: p.Type, - CategoryCode: p.Typecode, - City: string(p.City), - CityCode: string(p.CityCode), - Longitude: lng, - Latitude: lat, - BusinessArea: string(p.BusinessArea), - Website: string(p.Website), - RawData: string(rawBytes), - }) + requestUrl := baseUrl + "?" + params.Encode() + + response, err := g.Client().Get(ctx, requestUrl) if err != nil { - g.Log().Warning(ctx, "缓存POI数据失败", "poiId", p.Id, "error", err) + g.Log().Warning(ctx, "高德API请求失败", "error", err) + return nil, 0, err } + defer response.Close() + + var amapResp amapResponse + if err := json.Unmarshal(response.ReadAll(), &amapResp); err != nil { + g.Log().Warning(ctx, "高德API响应解析失败", "error", err) + return nil, 0, err + } + + if amapResp.Status != "1" { + g.Log().Warning(ctx, "高德API返回错误", "info", amapResp.Info) + return nil, 0, gerror.New(amapResp.Info) + } + + return amapResp.Pois, gconv.Int(amapResp.Count), nil +} + +// fetchAmapPage 调用高德文本搜索单页接口 +func (s *poiService) fetchAmapPage(ctx context.Context, apiKey, baseUrl, keywords, city string, page, offset int) ([]*amapPoi, int) { + params := url.Values{} + params.Set("key", apiKey) + params.Set("keywords", keywords) + params.Set("offset", gconv.String(offset)) + params.Set("page", gconv.String(page)) + params.Set("extensions", "all") + if city != "" { + params.Set("city", city) + } + + requestUrl := baseUrl + "?" + params.Encode() + + response, err := g.Client().Get(ctx, requestUrl) + if err != nil { + g.Log().Warning(ctx, "高德API请求失败", "error", err) + return nil, 0 + } + defer response.Close() + + var amapResp amapResponse + if err := json.Unmarshal(response.ReadAll(), &amapResp); err != nil { + g.Log().Warning(ctx, "高德API响应解析失败", "error", err) + return nil, 0 + } + + if amapResp.Status != "1" { + g.Log().Warning(ctx, "高德API返回错误", "info", amapResp.Info) + return nil, 0 + } + + return amapResp.Pois, gconv.Int(amapResp.Count) } func parseLocation(location string) (float64, float64) { diff --git a/common/base_dao.go b/common/base_dao.go deleted file mode 100644 index 7e42fcc..0000000 --- a/common/base_dao.go +++ /dev/null @@ -1,53 +0,0 @@ -package common - -import ( - "context" - - "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/os/gtime" - "github.com/gogf/gf/v2/util/gconv" -) - -func prepareInsertData(data any) map[string]any { - m := gconv.Map(data, gconv.MapOption{Tags: []string{"orm"}}) - delete(m, "id") - m["created_at"] = gtime.Now().Format("Y-m-d H:i:s") - m["updated_at"] = gtime.Now().Format("Y-m-d H:i:s") - delete(m, "deleted_at") - return m -} - -func InsertAndReturnId(ctx context.Context, table string, data any) (id int64, err error) { - m := prepareInsertData(data) - r, err := g.DB().Model(table).Ctx(ctx).Data(m).Insert() - if err != nil { - return 0, err - } - if r == nil { - return 0, nil - } - return r.LastInsertId() -} - -func GetOneByPk[T any](ctx context.Context, table string, pk int64) (res *T, err error) { - r, err := g.DB().Model(table).Ctx(ctx). - Where("id", pk).One() - if err != nil { - return nil, err - } - if r == nil { - return nil, nil - } - err = r.Struct(&res) - return -} - -func UpdateByPk(ctx context.Context, table string, pk int64, data any) error { - _, err := g.DB().Model(table).Ctx(ctx).Data(data).Where("id", pk).Update() - return err -} - -func DeleteByPk(ctx context.Context, table string, pk int64) error { - _, err := g.DB().Model(table).Ctx(ctx).Unscoped().Where("id", pk).Delete() - return err -} diff --git a/config.yml b/config.yml index 35131b9..39a7f7a 100644 --- a/config.yml +++ b/config.yml @@ -1,11 +1,5 @@ -database: - default: - name: pointly_tel.db - type: sqlite - debug: false server: address: :3000 name: pointly-tel amap: api_key: "884d33aef9842e60b840e2b2b6aedce9" - api_url: "https://restapi.amap.com/v3/place/text" diff --git a/go.mod b/go.mod index 42d68f6..9776cd8 100644 --- a/go.mod +++ b/go.mod @@ -2,19 +2,14 @@ module pointly-tel go 1.26.1 -require ( - github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.10.2 - github.com/gogf/gf/v2 v2.10.2 -) +require github.com/gogf/gf/v2 v2.10.2 require ( github.com/BurntSushi/toml v1.5.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect github.com/emirpasic/gods/v2 v2.0.0-alpha // indirect github.com/fatih/color v1.18.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/glebarez/go-sqlite v1.21.2 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/google/uuid v1.6.0 // indirect @@ -27,7 +22,6 @@ require ( github.com/olekukonko/errors v1.1.0 // indirect github.com/olekukonko/ll v0.0.9 // indirect github.com/olekukonko/tablewriter v1.1.0 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rivo/uniseg v0.2.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/otel v1.38.0 // indirect @@ -38,8 +32,4 @@ require ( golang.org/x/sys v0.35.0 // indirect golang.org/x/text v0.25.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - modernc.org/libc v1.22.5 // indirect - modernc.org/mathutil v1.5.0 // indirect - modernc.org/memory v1.5.0 // indirect - modernc.org/sqlite v1.23.1 // indirect ) diff --git a/go.sum b/go.sum index 21455c1..49c5e30 100644 --- a/go.sum +++ b/go.sum @@ -4,29 +4,21 @@ github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyM github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emirpasic/gods/v2 v2.0.0-alpha h1:dwFlh8pBg1VMOXWGipNMRt8v96dKAIvBehtCt6OtunU= github.com/emirpasic/gods/v2 v2.0.0-alpha/go.mod h1:W0y4M2dtBB9U5z3YlghmpuUhiaZT2h6yoeE+C1sCp6A= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= -github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.10.2 h1:KLS68SWS2W749x7e+eCCOO3UD2Sbw+bIbLEPR8o1FXw= -github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.10.2/go.mod h1:uLcsu73PfpyhRc0Jq0gGAWQjN1tyGU9iBRrYgt/lu7g= github.com/gogf/gf/v2 v2.10.2 h1:46IO0Uc8e85/FqdftJFskfDejJLBL0JBnGS5qOftUu8= github.com/gogf/gf/v2 v2.10.2/go.mod h1:Svl1N+E8G/QshU2DUbh/3J/AJauqCgUnxHurXWR4Qx0= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= -github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= @@ -54,9 +46,6 @@ github.com/olekukonko/tablewriter v1.1.0 h1:N0LHrshF4T39KvI96fn6GT8HEjXRXYNDrDjK github.com/olekukonko/tablewriter v1.1.0/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= @@ -90,11 +79,3 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE= -modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY= -modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= -modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= -modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM= -modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk= diff --git a/main.go b/main.go index 95adf0e..3f2c7d5 100644 --- a/main.go +++ b/main.go @@ -3,8 +3,6 @@ package main import ( "pointly-tel/amap/controller" commonHttp "pointly-tel/common" - - _ "github.com/gogf/gf/contrib/drivers/sqlite/v2" ) func main() { diff --git a/web/package-lock.json b/web/package-lock.json index f673c64..8bd272d 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "dependencies": { "axios": "^1.7.0", + "leaflet": "^1.9.4", "vue": "^3.5.0" }, "devDependencies": { @@ -1403,6 +1404,12 @@ "node": ">= 6" } }, + "node_modules/leaflet": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", + "license": "BSD-2-Clause" + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", diff --git a/web/package.json b/web/package.json index 7327aae..6e76f56 100644 --- a/web/package.json +++ b/web/package.json @@ -9,8 +9,9 @@ "preview": "vite preview" }, "dependencies": { - "vue": "^3.5.0", - "axios": "^1.7.0" + "axios": "^1.7.0", + "leaflet": "^1.9.4", + "vue": "^3.5.0" }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.0", diff --git a/web/src/App.vue b/web/src/App.vue index 33fd252..87664ce 100644 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -1,82 +1,101 @@ diff --git a/web/src/api/poi.js b/web/src/api/poi.js index 35d0c2e..8f7b08c 100644 --- a/web/src/api/poi.js +++ b/web/src/api/poi.js @@ -5,11 +5,12 @@ const api = axios.create({ timeout: 30000, }) -export async function searchPoi(keywords, city = '', page = 1, offset = 20) { - const params = { keywords } +export async function searchPoi(keywords, city = '', page = 1, offset = 20, longitude = 0, latitude = 0, radius = 3000) { + const params = { keywords, page, offset } if (city) params.city = city - params.page = page - params.offset = offset + if (longitude) params.longitude = longitude + if (latitude) params.latitude = latitude + if (radius) params.radius = radius const res = await api.get('/poi/search', { params }) return res.data.data diff --git a/web/src/components/PoiMap.vue b/web/src/components/PoiMap.vue new file mode 100644 index 0000000..735afcc --- /dev/null +++ b/web/src/components/PoiMap.vue @@ -0,0 +1,185 @@ + + + + +