我用腾讯位置服务做了一个会思考的选址地图

小雨青年 小雨青年
征文大赛 2026-05-21
我用腾讯位置服务做了一个会思考的选址地图

【腾讯位置服务开发者征文大赛】我用腾讯位置服务做了一个会思考的选址地图

作者: 小雨青年 发布时间: 已于 2026-04-17 18:07:36 修改
来源: https://blog.csdn.net/diandianxiyu/article/details/160232698


文章目录

  • 前言一、选址场景最适合把 AI 和地图真正接起来二、腾讯位置服务是工程底座三、如何使用 AI 串联为可用流程四、项目结构和核心代码展示五、在开发过程中不断提升用户体验总结

前言

做门店选址的人,几乎都会遇到同一种混乱。地图开着,搜索框里塞满了关键词,办公楼看一圈,地铁站看一圈,商场看一圈,竞品门店再看一圈,页面上的信息越来越多,脑子里的判断却越来越散。地图把很多内容放到了你面前,可真正麻烦的地方一直没变,那就是这些内容怎么拼成一个可以落下来的结论。

MapSite AI 就是从这里长出来的,我想做一个面向真实选址场景的 AI 地图应用。用户描述需求,系统去理解需求,再调用腾讯位置服务完成地点检索、候选区域筛选、地图展示和报告生成,最后给出一份可读、可比较、可导出的初筛结果。

地图在这里承担的是空间证据组织的工作,AI 负责理解和解释,最后交给决策者去判断。

体验地址:https://mapsite-ai.kaminono.com/

演示视频:

📹 嵌入式视频: https://live.csdn.net/v/embed/522091

MapSite AI 演示

一、选址场景最适合把 AI 和地图真正接起来

很多地图类项目一开始都会选择更容易展示的方向,比如自然语言搜周边、对话式导览、多人路线规划。这些方向都不错,也确实能体现 AI 和地图结合后的交互变化。可一旦把问题收得更贴近真实业务,你会发现商业选址这个场景的张力更强。

因为商业选址天生就是一个判断问题。用户关心的不是附近有什么,而是哪里更值得看,为什么值得看,和另外两个区域相比差距到底在哪。

这件事单靠地图页面很难跑通。地图可以展示信息,但不会自动帮你整理判断。单靠大模型也不行。大模型可以组织语言,却不能脱离真实空间数据凭空下结论。只有当地图能力和 AI 理解真正接起来,项目才会开始像一个产品,可以实际应用到具体的业务决策。

我在产品落地时,先拿咖啡店选址初筛作为主场景去跑通整条链路。这样做有两个现实原因。一个是咖啡店的需求足够常见,办公人群密度、地铁可达性、商业配套成熟度、竞品压力这些要素,是很容易被理解的。另一个是这类空间要素和腾讯位置服务的地点搜索、地图展示、行政区划、可视化能力的整合非常密切,产品更容易形成完整闭环。

image-20260415221303968

用户输入一段像面向白领、靠近办公楼、交通方便、竞争压力适中这样的自然语言需求,系统就能把它拆成可以执行的空间条件,分析数据之后,会生成候选区域、地图呈现和详细的评分分析。

不过,这个项目的能力边界并没有被限制在咖啡店上,这套方法同样可以延伸到轻食店、茶饮店、社区烘焙店、便利零售、小型宠物门店这类业态。它们关注的重点可能不同,有的更看重办公客群,有的更看重社区密度,有的更在意交通可达性和配套成熟度,但底层逻辑是一致的,都是先把自然语言需求翻译成结构化条件,再用腾讯位置服务提供的空间数据去完成候选区域筛选和结果解释。

地图进入真实业务场景以后,最重要的价值在于它开始参与判断过程。AI 进入这个场景以后,最重要的价值在于它能把模糊输入翻译成结构化条件,再把结果解释得更容易理解。

二、腾讯位置服务是工程底座

MapSite AI 能真正成立,靠的不是某一个大模型突然很聪明,而是腾讯位置服务把地图前端、LBS 服务和 WebService 能力做成了一整套可以拼起来的工程链。

平时说接地图,很容易把这件事想简单。真到产品开发阶段,你很快就会发现,地图不是放一个底图就结束了。地图实例怎么初始化,候选区域怎么画,多边形和点位怎么联动,图层怎么切,行政区划怎么接入首页城市选择,地点搜索怎么进入分析流程,这些事情全都要落下去。

腾讯位置服务的 Map Skills 在这里给了我很大的帮助。前端地图分析页搭建阶段,我用到了 TencentMap_jsapi_skills 对应的能力面。地图初始化、覆盖物绘制、图层管理、事件系统和可视化渲染,这些能力让地图页从一开始就有了比较清晰的开发路径。它没有替我自动完成产品设计,但明显减少了前端地图集成阶段的试错成本。地图分析页最后能做成候选区域高亮、点位联动、图层切换和区域详情同步,很大程度上就是因为这层能力足够扎实。

腾讯位置服务的 WebService 能力是整条选址分析链路的基础。地点搜索负责提供候选区域分析所需的核心空间数据,行政区划接口负责支撑首页城市选择与城市级分析范围的确定。两者进行衔接,产品的搜索边界、交互方式和结果输出就能自然统一到同一套逻辑里。地点搜索更适合城市级、圆形区域和矩形区域分析,这让选址结果能够稳定落在明确的空间范围内。行政区划接口又天然适合生成城市列表控件,因此首页交互最终收敛为核心城市快速选择。

还有一个很容易被低估的点,是地图可视化。JavaScript API GL 提供的点标记、信息窗体、多边形和更丰富的可视化能力,让地图分析页不只是看起来像个地图,而是真正能承载判断过程。左侧候选区域列表和右侧地图主视图是一起工作的。用户看分数的时候,地图上的区域高亮、竞品分布、办公点位和地铁站位置会同时给出空间证据。这样一来,腾讯位置服务在这个项目里的存在感就不需要靠反复强调来获得,因为每一层能力都直接参与了产品结果。

三、如何使用 AI 串联为可用流程

用户输入的永远是人话。系统需要的却是结构化条件。这中间如果没有一个可靠的转换层,地图分析一定会出现很大误差。项目里 AI 的第一个职责,就是把自然语言需求拆成城市、业态、目标客群、交通偏好、竞争容忍度和配套偏好这些字段。

结构化意图出来以后,服务端会基于腾讯位置服务检索办公点位、地铁站、商场、餐饮和竞品门店,再围绕这些空间要素生成候选区域。这里我没有做那种看起来很高级、实际很难解释的全城网格,而是把候选区域收成几类空间特征更明显的方向。办公导向型区域、交通导向型区域、商业配套导向型区域。这样处理以后,地图上的差异、左侧候选区域卡片和后面的报告解释才能真正对应起来。

评分模型也是项目里一个反复重写的部分。最早的版本分数虽然能算出来,但区分度很差。多个区域综合分一样,子项分数经常是满分或者低分,看起来更像硬阈值判断。后面我把这一层改成了连续值评分。客群匹配度和办公点位数量、密度、分布共同相关,交通便利度和地铁站数量、最近距离共同相关,竞争压力由竞品数量、密度和最近竞品距离共同影响,设施成熟度则围绕商场、餐饮和便利设施分布来估算。这个变化一出来,左侧候选区域列表终于有了层次,地图上的区域差异也开始真正服务于判断。

AI 在这条链路里的第二个职责,是结果增强解释。系统不会凭空推荐区域,解释总是在腾讯位置服务检索结果和评分结果之后出现。项目做到中后期,我还把增强链路改成了渐进式处理。基础分析先返回,让页面先可用,增强解释在后台继续跑。这个调整特别现实。因为真实项目里,模型响应速度、网络波动、配置问题都会影响链路稳定性。改成渐进式以后,用户先能看到地图和候选区域,再等待系统自动增强分析说明,整体体验会平顺很多。

这里还有一个很值得单独提出来说的地方。开发过程里,技能调用不是一个点缀,而是真实存在的工作流。前端地图分析页的搭建、交互和图层处理,我都配合 TencentMap_jsapi_skills 做过实际使用,大幅度降低了开发的工作量。

四、项目结构和核心代码展示

整体流程从首页输入开始,前端先完成城市选择与本地配置校验,再将需求提交到服务端分析入口;服务端一方面通过规则兜底快速生成首版分析结果,另一方面结合 AI 意图解析能力,将模糊需求拆解为目标客群、竞争容忍度、交通偏好等结构化条件。随后,系统调用腾讯位置服务的地理编码、POI 检索与空间数据能力,生成多个候选区域,并基于客群匹配、交通便利、竞争压力、设施成熟度等维度完成综合评分。最终,分析结果会同时落到地图分析页与报告页中:前者突出候选区域、竞品点位和交通设施的空间分布,后者则以更适合阅读和交付的方式输出结论,并支持打印版与 PDF 导出。

我们详细分析其中的地图分析页初始化与候选区域绘制页面。以下 核心代码的作用是负责加载腾讯地图 SDK、初始化地图实例、绘制候选区域多边形,以及叠加竞品/办公/地铁等 POI 图层。

useEffect(() => {
  // 本地配置还没加载完成时,先不做地图初始化
  if (!configLoaded) return;

  // 从当前配置中解析出前端可用的地图 Key
  const resolvedMapKey = resolveClientMapKey(config);

  // 如果没有地图 Key,直接进入错误态,并提示用户先完成配置
  if (!resolvedMapKey.hasMapKey) {
    setMapStatus("error");
    setStatusTitle("地图 Key 缺失,请先完成地图配置");
    return;
  }

  // 动态加载腾讯地图脚本
  // 这里 forceReload 为 false,表示如果页面里已经有脚本,就不重复加载
  loadTencentMapScript(resolvedMapKey.mapKey, { forceReload: false })
    .then(() => {
      // 脚本加载完成后,创建地图实例
      const map = new window.TMap.Map(mapContainerRef.current, {
        // 注意 TMap.LatLng 的顺序是 lat, lng
        center: new window.TMap.LatLng(centerCoord[1], centerCoord[0]),
        zoom: 13,
        viewMode: "2D",
      });

      // 保存地图实例,供后续图层绘制和事件绑定复用
      mapRef.current = map;

      // 创建一个全局复用的信息窗体
      // 后续点击点位或区域时,可以直接更新位置和内容
      infoWindowRef.current = new window.TMap.InfoWindow({
        map,
        position: new window.TMap.LatLng(centerCoord[1], centerCoord[0]),
        offset: { x: 0, y: -32 },
      });

      // 初始化后先关闭,避免默认展示空白信息窗体
      infoWindowRef.current.close();

      // 等到底图瓦片真正加载完成,再把地图状态切换为 ready
      // 这样可以避免地图容器已经渲染,但底图还没出来时的误判
      map.once("tilesloaded", () => {
        setMapStatus("ready");
      });
    })
    .catch(() => {
      // 地图脚本加载失败,进入错误态
      setMapStatus("error");
      setStatusTitle("腾讯地图脚本加载失败");
    });
}, [config, configLoaded, centerCoord]);

useEffect(() => {
  // 地图实例还没初始化完成时,不执行候选区域绘制
  // 如果当前已经是错误态,也直接终止
  if (!mapRef.current || !window.TMap || mapStatus === "error") return;

  const map = mapRef.current;

  // 根据当前图层开关,决定是否绘制候选区域多边形
  // 如果候选区域图层关闭,就传空数组
  const polygonGeometries = layers.candidates
    ? regions
        .map((region) => ({
          // 每个区域的唯一标识
          id: region.id,

          // 当前激活区域使用 active 样式,其余使用 normal 样式
          styleId: region.id === activeRegionId ? "active" : "normal",

          // 将后端返回的 [lng, lat] 坐标数组转成 TMap.LatLng 实例
          // 注意这里同样要转换成 lat, lng 顺序
          paths: (region.bounds || []).map(
            (coord) => new window.TMap.LatLng(coord[1], coord[0])
          ),

          // 预留附加属性,后续点击事件或信息窗体可以直接使用
          properties: { name: region.name },
        }))
        // 过滤掉没有边界数据的区域,避免创建无效多边形
        .filter((g) => g.paths.length > 0)
    : [];

  // 创建候选区域图层
  polygonsRef.current = new window.TMap.MultiPolygon({
    map,
    styles: {
      // 默认区域样式
      normal: new window.TMap.PolygonStyle({
        color: "rgba(59, 130, 246, 0.2)",
        showBorder: true,
        borderColor: "rgba(59, 130, 246, 0.8)",
        borderWidth: 2,
      }),

      // 当前选中区域样式
      active: new window.TMap.PolygonStyle({
        color: "rgba(239, 68, 68, 0.3)",
        showBorder: true,
        borderColor: "rgba(239, 68, 68, 1)",
        borderWidth: 3,
      }),
    },
    geometries: polygonGeometries,
  });

  // 监听区域点击事件
  // 点击后把区域 id 回传给上层,由上层统一更新当前选中状态
  polygonsRef.current.on("click", (e: any) => {
    if (e.geometry?.id) onRegionSelect(e.geometry.id);
  });
}, [mapStatus, regions, activeRegionId, onRegionSelect, layers]);

五、在开发过程中不断提升用户体验

作为一名从开发一路走过来的产品经理,我充分理解,能跑通和能上线是两回事。一个页面能展示结果,不代表它已经像一个产品。这个项目往前推进的时候,我越来越在意一个问题,用户第一次打开以后,能不能很顺地理解整个流程。也正因为这样,后面的很多交互都做了进一步优化。

城市选择器,从全量搜索,一路收回到核心城市快速选择,原因很现实。产品现在的目标是让用户尽快进入分析,而不是先在首页做复杂筛选。

右上角的本地连接设置也做了专门优化。地图和 AI 配置都由用户自己提供,配置只保存在当前浏览器中,这样项目上线以后不会默认消耗绑定账号,用户都也可以直接拿自己的应用的 Key 来体验。这个取舍对产品上线很重要。它决定了项目到底是一个只能本地演示的工程稿,还是一个别人能真正点开试用的产品原型。

报告页是另一个让我觉得项目终于成形的地方。地图页负责空间判断,报告页负责把结论沉淀下来。需求摘要、候选区域总览、首推区域分析、评分方法说明、风险提示、下一步建议,再加上打印版和 PDF 导出,这一整套内容出现以后,产品就不再只是一个有地图的分析页面,而开始有了可交付结果。对选址这类场景来说,这一步特别关键。因为很多判断最后都要回到讨论和决策上,报告把地图里的空间证据沉成了人能带走、能复盘的东西。

项目走到这里以后,腾讯位置服务的价值也会变得更清楚。它在这个产品里提供的,从来都不只是地图底图。首页城市选择要靠行政区划能力收住交互,地图分析页要靠 JSAPI GL 把区域、图层和点位联动起来,候选区域分析要靠地点搜索拿到空间要素,报告里的判断也都建立在这些结果之上。

总结

MapSite AI 做下来,我最清楚的一点就是,地图一旦进入真实业务场景,价值是巨大的。

它不再只是把信息放到页面上,而是开始参与理解、筛选和判断。腾讯位置服务给了这个项目一个非常扎实的底座。Map Skills 让前端地图页在开发过程中更容易执行,地点搜索、行政区划和地图可视化能力让选址分析真正有了空间依据。AI 把自然语言理解和结果解释接了上来,最后从输入到报告,形成了一个完整闭环。

MapSite AI 现在已经是一个可以体验、也可以继续迭代的产品原型。对这种项目来说,真正有说服力的地方,永远都在那些上线以后用户能马上感受到的细节里。腾讯位置服务在这里的意义,也正是在这些细节里被一步一步放大出来的。

* AI润色输出,仅供参考

我们为您提供位置服务商业授权许可

合规地图省心之选,微信生态独家支持

办理咨询

相关推荐

腾讯位置服务地图定位解决方案:精准搜索与高效定位的技术实践

叮小灵 叮小灵

在智慧出行本地生活零售选址等场景中,地图定位不仅是基础功能,更是连接用户需求与商业价值的桥梁。腾讯位

地图定位 2026-03-02

腾讯位置服务开源地图API:技术特性与多场景实践指南

叮小灵 叮小灵

在移动应用车载导航智慧城市等领域,地图API的灵活性与可扩展性直接影响开发效率与用户体验。腾讯位置服

开源地图 2026-03-03

腾讯位置服务地图软件开发:路线规划功能如何赋能开发者与行业场景?

叮小聪 叮小聪

在地图软件开发领域,精准的路线规划能力是连接用户需求与位置服务的核心纽带。无论是出行导航物流配送,还

路线规划 2026-03-02