御坂个人足迹地图:从需求到AI开发上线

御坂个人足迹地图:从需求到AI开发上线
Misaka10013在大概10年多前,我就已经在使用谷歌足迹地图,最早是在使用谷歌地球中觉得精确、细节拉满的谷歌地球很适合找到一些自己去过的地方并且标点记录。之后我在我的博客的“关于”页面,通过链接谷歌足迹地图的方式,在我的博客实现查看我的足迹。
1 | <iframe src="https://www.google.com/maps/d/embed?mid=1FnQqdlXYFoEnO6WvZ8QEHj9RYHg" width="100%" height="600"></iframe> |
但使用上也有一些痛点。例如谷歌地图一直被强,我更新足迹需要总是用梯子,所以更新频次很少。其次是谷歌卫星地图和地图道路、点位等信息在国内的部分有坐标偏差,查看起来很难看。经常我一个点位不知道按卫星地图给标记还是按街道位置进行标记。近几年,我也断断续续用过其他方案,例如百度地图或者高德收藏夹存地点。但每次想回顾”我去过哪些地方、在那里发生过什么”的时候,数据总是散落在各个 App 里,我要打开app去翻找,宁琅满目各种广告、贷款推荐,慢得很。
我想要的东西其实很简单:一张属于我自己的地图,每个点位是一段记忆,能写文字、能贴图、能按时间连成路线,数据永远在我手里。
于是在AI的协助讨论和开发下,就有了这个项目——一个嵌入 Hexo 博客的纯前端足迹地图。这篇文章记录它从需求讨论到上线的完整过程,包括踩过的三个很有代表性的坑,以及留给以后的待办事项。
一、需求对齐:和元宝的两轮讨论
这个项目我没有直接让 AI 上来就写代码,而是先找了元宝聊需求,在多轮的聊天中不断让AI发问,问询我自己,把自己的需求探明。这个过程也是把自己的思路想清楚。
我和元宝从”我想记录人生足迹”这个模糊的念头开始聊,逐步收敛出核心功能:地图标记、分类体系(路程/好吃的/好喝的/好玩的/风景/兴趣点)、Markdown 图文弹窗、按时间排序的路线模式、分组筛选、数据导入导出。
聊完之后,元宝帮我产出了两份文档:
| 文档 | 面向对象 | 侧重点 |
|---|---|---|
| 需求与功能设计文档 | 人类阅读 | “做什么”和”为什么”,交互规则 |
| AI 开发者移交文档 | AI 开发者 | 数据模型、优先级(P0/P1/P2)、验收清单、开发约束 |
第一个文档相当于面向用户的需求描述,第二份文档则相当于面向AI开发的开发实践指南。不过我在实际应用的时候觉得,最好不要让动手开发的AI完全被第二份开发者指南所左右。有时候不同AI的思维能力还是不一样的。而且在具体实践中的AI,配合人的测试,总能发现一开始技术设计思路上与实际情况的不一致。
之所以一开始想到和AI先聊方案,主要是我自己在政务系统工作实践中,也经常需要和客户一边对着原型,一边不断讨论,这个是摸清需求,很重要。要不然后期真正做的时候,就会是无限的改版。而AI开发,虽然AI不会累,可以反复的改版,但模糊需求的话,我的token和时间也是成本。一开始,尽量从需求文档层面把方向描述得越精确,AI 找到正确的方案实现的概率最高,也减少来回扯皮的次数越少。
我觉得,和干活的人沟通,一定要言语高效。和AI沟通描述想法,是一个很好的训练工作协作和沟通思路的方法。另外我曾经也经历过项目长了、项目和用户的交互多了,最后反而一堆问题。和AI协同编程,我觉得最恐怖的应该是,好不容易搭建起来一个基本完美的作品了,后面让AI修修bug,然后把前面的功能搞崩了。哈哈哈。所以开发的过程中,我也叮嘱AI注意每个版本的备份。
在开发前,我也是和AI沟通,并且找了相似的需求方案,作为我们开发的参考。减少凭空造轮子的情况。参考了 MarkdownMap、leaflet-search、Exping 三个项目的架构思路。
前期建设原则基本上定下来:
- 纯前端:无后端、无数据库,静态托管就能跑
- 数据自主:所有数据是 JSON 文件,随时导出,永不锁定
- 单文件交付:CSS 和 JS 全部内联进一个
index.html,扔进source/map/就能用
二、开发实施:和 WorkBuddy 的六轮迭代
文档交给 WorkBuddy 后,很快我们迭代了六个版本出来。把迭代过程整理成一张表:
| 版本 | 主要内容 | 性质 |
|---|---|---|
| v1 | 按移交文档实现全部功能 | 初版 |
| v2 | 外部依赖内联化,提高可用性 | 优化 |
| v3 | 数据结构调优 | 优化 |
| v4 | 修复”弹窗关闭后无法再打开” | 修坑 |
| v5 | 搜索下拉遮挡修复 + 回车选中 + OSM/Carto 底图 | 修坑 + 衍生 |
| v6 | 图层循环切换改为下拉选择器 + Esri 卫星底图 | 衍生需求 |
初版(v1~v3)出乎意料地顺利——移交文档写得细,AI 基本一次成型,验收清单里绝大部分条目直接通过。真正花时间的是后面三轮,属于是由我在使用中来检验和测试bug,并且评估是否满足我的使用需求。
三、踩坑记录
坑 1:弹窗关闭后无法再打开(v4)
现象:点击地图点位,弹窗正常弹出。点弹窗右上角 ✕ 关闭后,再点同一个点位,弹窗死活不出来了。刷新页面,又能打开一次。
这个 bug 特别有迷惑性——“第一次能开”说明打开逻辑没问题,”关了就开不了”说明关闭操作把什么东西弄脏了。我负责通过不同的操作定位的故障现象和日志,由AI来定位bug原因。
AI挖到是 Leaflet 源码层面。Leaflet 的 Marker._openPopup 内部有一个切换逻辑:
1 | _openPopup: function (t) { |
而AI按我需求自定义编写的 click 处理器和 Leaflet 内部的这个处理器同时在监听点击。两者出现冲突。属于是用参考第三方库给自己引入的麻烦。所以说,当CV工程师可不行。哈哈。
四、衍生需求:在使用中改进
这三个功能不是在最初的需求文档里,而是使用中存在痛点又提出来的:
- 国外底图。原本用高德瓦片,国内还算清晰,但我想标记国外的点,一放大全是空白。于是加了 OSM 和 Carto 浅色两种国外底图,再加 Esri 卫星,凑齐了”国内+国外、标准+卫星”的完整组合。
- 图层下拉选择器。底图从 2 种涨到 5 种之后,原来的”循环切换”按钮变得很蠢——想要 Esri 卫星得连按四下。改成下拉选择器。
- 搜索回车选中。发现下拉结果被遮挡的过程中,发现自己习惯性按回车搜索确认,让AI增加。
五、隐私考量:一个暂缓的决定
上线前我想到一个问题:这个页面不需要登录,我自己看很方便,但别人也同样方便地能看到我的全部足迹——我去过哪、什么时候去的、写了什么。
我原本在两个方案间犹豫:给页面加个密码锁,还是让页面正常访问但数据加载要验证。但和 AI 讨论后,一时间没想出来好办法:静态托管没有后端,任何”前端验证密码”都只是遮羞布——绕过页面直接访问 data.json 的 URL,明文数据照样下载。
真正有效的方案是第三种:把 data.json 本身用 AES-256-GCM 加密,密码只存在于我脑子里。浏览器端负责解密渲染和加密导出,别人就算下载到文件也只是一堆乱码。但我也想保留地图的便利分享和展示能力。一时间没想好具体怎么处理。
六、上线部署
部署方式简单:把 source/map/ 整个文件夹(index.html + data.json + README.md,共 3 个文件)复制到正式仓库目录,git push,CNB 云原生构建自动完成后续一切。
上线后访问 https://misaka10013.cn/map/。
整个项目的技术栈,最后总结成一句话:Leaflet.js 管地图,marked.js 管 Markdown 渲染,localStorage 管持久化,原生 JS + 内联 CSS 管一切交互,零框架零后端零构建。
七、待议与待办(给未来的自己)
把未完成的事项记在这里,以后翻到这篇文章就知道下一步往哪走:
| 事项 | 说明 | 优先级 |
|---|---|---|
| data.json 加密 | AES-256-GCM + PBKDF2 方案,客户端解密渲染;导出备份同样加密 | 高 |
| 地图页入口 | 目前无导航/文章链接指向 /map/,纯 URL 直达(算是一层隐蔽) | 低 |
后记
复盘整个项目,我的流程是:元宝做需求收敛和文档产出,WorkBuddy 做编码实施,我做真实环境测试和方向决策。 三个角色里,AI 承担了两块,而指引方向和评估质量由我来把控。
更新记录(2026-09-23):上线之后的 v7 → v20
上面这篇文章写到 v6 上线就收尾了。但真实用起来之后才发现,上线只是开始。这一个多月里我又断断续续和AI迭代了十几版,把一些细节问题处理了。这次更新把后续补上。
v7 ~ v9:真实数据进场,连踩三个坑
上线的第一个动作是把我的真实足迹数据搬进来。流程是:把谷歌地图 Takeout 导出 KML → 脚本转 Excel(我人工过一遍分类)→ 让AI出脚本批量转 data.json → 导入数据到足迹网页。276 个点位,时间从 2018 年排到 2019 年。
数据一进来,问题立刻炸出来三个:
| 版本 | 问题 | 根因 |
|---|---|---|
| v7 | 点位名全显示 undefined,编辑框空白 |
导入的data数据点位名用 name 字段,而网页代码却在读 m.title,让AI修复 |
| v7 | 保存编辑后弹窗关闭按钮失效 | 保存时重建了 marker,但新弹窗没重新绑定事件。AI的bug |
| v8 | 改了点位时间,连线序号不变 | 时间格式问题 |
| v9 | 同一个点在高德和 Esri 上位置差几百米 | 坐标系不一致 |
v7 那个字段错乱:data数据和网页代码的字段名各写各的,没想到AI居然能翻这种错误,只能说AI能写代码,但有时候就是会犯低级错误,很像上下文记忆导致的问题。测试数据少的时候根本看不出来,数据一多就爆bug。
坑 4:日期格式的”半个格式”(v8)
现象:我把一个点位的日期改了,保存,连线序号纹丝不动。导出 JSON 再导入,顺序还是老样子。原因是因为
- KML 导出的时间是
"2018-01-01"——只有日期,没有时分 - 而HTML网页 的
<input type="datetime-local">只认YYYY-MM-DDTHH:MM这种完整格式,遇到"2018-01-01"它不报错,也不提示,就是静静显示成空白 - 我打开编辑弹窗,看到时间框是空的,以为”原本就没填”,改完别的字段就点保存
- 保存逻辑把空值写回去——
m.time = '',时间被我亲手清空了 - 连线功能有个过滤条件
m.time && m.time !== '',时间空了的点直接被排除出连线列表——所以”序号没变”其实是”这个点根本不参与排序了”
修复:拉着所有点位数据,时间统一按 YYYY-MM-DD 00:00补全数据。
坑 5:坐标系——地图项目躲不开的一道坎(v9)
现象:国内的地图清晰度真一般,我给页面加了 OSM、Carto、Esri 这些国外底图后,但切过去一看,又遇到了以前谷歌地点的问题。所有点位都偏了——在国内大概偏几百米。这个问题我们的一些政务系统也经常见,撒点因为坐标系不同,总是容易对不上位置。
根因:国内地图服务(高德、百度、腾讯)用的是 GCJ-02(俗称火星坐标系,法律要求下加了非线性偏移),国外服务(OSM、Esri、Carto)用的是 WGS-84。同一组经纬度,在两套坐标系里指的不是同一个地方。好在大家用的啥,偏移多少,是个已知的事情。那这个问题就有解。
统一以 GCJ-02 存储(和主用的国内底图原生一致),渲染前判断当前底图——如果是 WGS-84 国际底图,就把坐标反算成 WGS-84 再摆上去;反过来,我在网页上新增点位或定位输入时,把显示的 WGS-84 坐标转回 GCJ-02 再存。
v10 ~ v13:把 277KB 的单文件拆开
我观察到AI编码的我的足迹地图代码越来越大,但他一直放在一个文件里面。其中样式、js文件都在其中,每次版本迭代,AI就要读取全文件,很快上下文窗口就不够用了,AI疯狂降智。这意味项目已经开始不小了,复杂度上去了。肯定就得拆分框架了。html、js、css全部分离。
| 版本 | 需求 | 结果 |
|---|---|---|
| v10 | 点位可按时间区间筛选(点位+轨迹一起裁) | 加了”全部/近1年/近3年/自定义”,默认近 1 年 |
| v11 | AI对单文件已经改不动了 | 277KB 拆成 index.html(4.7KB) + app.js + style.css |
| v12 | 对200KB+的app.js继续拆分优化 | 78% 是第三方库,将第三方库抽离出去,避免AI每次读自己写的主要逻辑代码都要读第三方库js,抽到 vendor/,业务代码只剩 56.6KB / 1634 行 |
| v13 | 申请到天地图 Key,增加更加清洗的国内卫星图源 | 加了天地图卫星底图(影像 + 中文注记叠加) |
v12 这种情况值得主意:一个项目持续干下去,量级大了,很容易超过AI的处理能力。拆分、解耦是好方法。
v14 ~ v20:隐私方案从”遮羞布”做到真加密
这是最近这次迭代的主线,也是之前第五节那个”暂缓的决定”最终的落地过程。方案改了三次:
| 版本 | 方案 | 为什么被推翻 |
|---|---|---|
| v14 | 全页访问锁:进页面就要密码 | 但这个方案其实挡不住别人直接下载访问 data.json,只是阻挡电脑小白。而且这个方案下也让一些值得和其他人分析的分私密点位不可见了 |
| v15~v16 | 点位级私密:点位加”是否私密”属性,未解锁不显示 | 只藏该藏的。但数据仍是明文,仅仅是”界面不显示”,了解互联网的人一样可以探索网页的架构并下载data.json获取所有隐私点位数据 |
| v19 | 真加密:公开点明文 + 私密点整块密文 | 这是最终头脑风暴出来敲定的方案 |
v19:加密落地
最后把真加密这个方案真正做完了,核心一句话:别人下载到 data.json 也只是一堆乱码。
- 单文件混合:公开点位保持明文(页面正常打开、公开点正常显示),私密点位整块数组加密成一个密文块——连”有几个私密足迹点”都看不出来
- 算法:PBKDF2-SHA256 迭代 60 万次派生密钥 → AES-256-GCM(12 字节随机 iv、128 位认证标签)
更新后的待办(给未来的自己)
| 事项 | 状态 |
|---|---|
| ✅ 已完成(v19) | |
| ✅ 已加返回按钮(v17),文章链接待补 |
一点感受
从最近半年从事搞政务大屏系统的时候,我就开始有了想法,要搞个自己的地图。
一开始搞的时候,几个版本就把地图做出来了,但没想到不断使用的过程中,居然衍生改版了近20个版本出来。不过这也正常,从来没有什么是一个版本就可以把自己的需求描述完的。在使用中总是伴随着需求优化和bug处理。不过我还是比较惊讶AI的能力,整个过程不断在试探AI的能力边界,AI虽然磕磕绊绊,但最后总归还是都实现了。





