用户要求这份记忆跟着仓库走,而不是只留在本机。 .gitignore 里挡路的是 `.workbuddy/`。改成反忽略六行,并且**只放行 .md**: 别用 `!.workbuddy/memory/**`——它会把 memory 下任何文件都放行,本项目真发生过 `web.test.exe` 混进暂存。复核用 `git check-ignore -q --no-index` 逐条打靶: memory/*.png、memory/sub/x.md、memory/MEMORY.md.bak、plans/a.md 全 IGNORED, 17 个 .md 全 included;`git add -An .workbuddy/` 恰好 16 个文件。 其余 .workbuddy 内容(计划、本地设置、临时产物)继续忽略。记忆里没有真凭据 (唯一命中是 2026-09-14.md 里的 `password=rond-admin`,那是项目默认口令)。 顺带做两件整理: 1. 取证了注入上限。以前按「字节数」判断 MEMORY.md 是否超限是错的: WorkBuddy 的 `getWorkingMemoryContent()` 用 `MAX_MEMORY_CHARS = 1e4` 比 JS `content.length`,即**字符数**(中文 1 字算 1);超了 substring 截断、尾部静默丢失。 本 details 与每日日志都不参与注入,只有 MEMORY.md 受约束。 现已从 6604 字符收到上限的 66%,并把这条上限写进索引抬头。 2. 把「备份合并」「导出/恢复三条铁律」两段长文迁进 MEMORY-details.md 的卅一/卅二节, 索引只留关键词指针。行尾统一为 LF(仓库 .gitattributes 是 `* text=auto eol=lf`)。
239 lines
19 KiB
Markdown
239 lines
19 KiB
Markdown
# 2026-09-14
|
||
|
||
## rond-with-you:把 rond 备份变成足迹站点(从零建成可运行版本)
|
||
|
||
### 背景
|
||
用户提供 `data/20260914_151649.rondbackup`(3.4MB),要求做一个后台可上传该文件、
|
||
前台展示足迹地图 / 类型 / 日期筛选的站点。技术栈由用户指定为 PostgreSQL(本地测试环境
|
||
`postgres / 127.0.0.1:5432`),后端语言 Python 或 Go 自选。
|
||
|
||
### 备份结构(已实测确认)
|
||
`.rondbackup` 是 zip,内含 Core Data 库 `LifeEasy.sqlite` + `-wal` + `-shm`。
|
||
**关键点:数据几乎全在 WAL 里**(主库 348KB / WAL 3MB),必须三个文件一起解出再打开,
|
||
否则只能读到极少量记录。Core Data 时间戳基准为 2001-01-01 UTC。
|
||
|
||
主要表与本次数据量:`ZVISIT` 824、`ZLOCATION` 323、`ZRAWVISIT` 2246、`ZMOVEMENT` 791、
|
||
`ZACTIVITY` 30、`ZHOURLYWEATHER` 557、`ZTAG` 8、`ZTRANSPORT` 5、`ACHANGE` 4810(未导入)。
|
||
标签关联表命名规则为 `Z_<实体号>TAGS_`,如 `Z_11VISITS_` = Visit↔Tag(11=Tag,18=Visit)。
|
||
|
||
导入结果:823 条到访(跳过 1 条到达时间缺失的空记录)、323 地点、8 标签关联、791 位移、
|
||
557 天气;跨度 2025-02-10 ~ 2026-09-13,估算里程 16861.9km,城市 9 座 / 省份 2 个。
|
||
|
||
### 技术选型
|
||
- Go 1.25 + 标准库 net/http + html/template(未引入 Web 框架)
|
||
- PostgreSQL + `pgx/v5`;备份解析用纯 Go 的 `modernc.org/sqlite`(无 cgo)
|
||
- 前端手写 CSS,Leaflet + markercluster 本地内置(无 CDN 依赖)
|
||
- 口令 PBKDF2-SHA256(标准库 `crypto/pbkdf2`);会话为 HMAC 签名 Cookie,
|
||
签名混入口令摘要前缀,改密即让旧会话失效
|
||
|
||
### 踩过的坑(都已修复)
|
||
1. `//go:embed static` 的资源路径相对包目录,原放在仓库根的 `web/` 下会编译失败,
|
||
已移动到 `internal/web/{templates,static}`。
|
||
2. 地点查询用 `WHERE ... EXISTS (SELECT ... visits v` + `inner.SQL()[7:]` 拼接,
|
||
切片把 `WHERE` 关键字一起去掉了,导致 `SQLSTATE 42601`。改为 `inner.expr()` 并给
|
||
子查询占位符加偏移(`where.off`),避免与外层 `$1` 冲突。
|
||
3. 模板函数 `dur` 形参写死 int64,而 `VisitRow.DurationMin` 是 int,渲染时报
|
||
"wrong type for value",改成接受 `any`。
|
||
4. 页面模板若共用 `templates/*.html` 一次性 ParseFS,各页 `{{define "content"}}`
|
||
会互相覆盖;改为每个页面与 layout 单独组成模板集。
|
||
5. 月度图表只查有数据的月份,会把空档压缩掉;改为补齐成连续月份序列并标注年份。
|
||
6. 移动端导航会折行撑坏布局,窄屏改为隐藏站点名、导航横向滚动、按钮文案缩短。
|
||
地图缩放/图层控件在窄屏改挂右下角,避免与全宽筛选面板重叠。
|
||
|
||
### 环境备忘
|
||
- `GOPROXY=https://goproxy.cn` 可用;`proxy.golang.org` 不通
|
||
- jsdelivr 可下载前端库;高德瓦片 `webrd0X/webst0X.is.autonavi.com` 可直连
|
||
- playwright-cli 通过 `npx --yes @playwright/cli@latest` 调用;**浏览器进程会在两次
|
||
bash 调用之间被回收**,open / goto / screenshot 必须放在同一次调用里
|
||
|
||
---
|
||
|
||
## 第二轮:地图偏移 + 重复导入 + 隐私默认 + 底图配置(P0/P1 收尾与回归)
|
||
|
||
### 坐标结论(已实测,写进 README 了)
|
||
rond 入库的 `ZLOCATION` / `ZRAWVISIT.ZLATITUDE` **本来就是 GCJ-02**,不是 WGS-84。
|
||
证据两条:① 2246 个采样点「解析坐标 − 原始 GPS」中位差 lat −0.002823 / lon +0.004187,
|
||
与 GCJ-02 理论偏移(−0.002825 / +0.004187)残差 0 米;② 与世界迷雾覆蓋比对,
|
||
逆 GCJ→WGS 后命中率 92.3%,直接用原始值只有 32.8%。
|
||
→ 高德 / 天地图这类 GCJ-02 底图**直接画,不要再纠偏**;只有 WGS-84 底图才做 GCJ→WGS 逆变换。
|
||
旧代码对每个点都套了一次 `gcj()`,所以叠了约 1.1km 的双重偏移。
|
||
|
||
### 底图配置
|
||
`conf/app.ini`:`map_provider` = amap(默认免密钥)/ tianditu(需 `map_key`)/ custom
|
||
(需 `map_tile_url` + `map_crs`)。填了 `map_key` 后瓦片走服务端代理 `/tiles/{layer}/{z}/{x}/{y}`,
|
||
密钥不出现在页面源码;无密钥则浏览器直连。前端读 `/api/map-config` 拿 `crs` 决定要不要逆变换,
|
||
切换底图时重新投影已有标记。
|
||
|
||
### 本次修掉的三个 bug(都是实测复现过的)
|
||
1. **瓦片代理子域写死 0** → 高德子域只有 01~04,`webrd00` / `wprd00` 根本不解析。
|
||
改为按 `(x+y)%count` 轮转,高德 1..4、天地图 0..7。代理模式实测 4 张瓦片全部 200。
|
||
2. **`Stats.Skipped` 从未赋值**(`ingest.go` 构造 Stats 时漏了字段)→ 「已跳过 N 条」
|
||
与「内容完全重合」两个提示全是死代码。补上后实测提示正常。
|
||
3. **`movements` INSERT 不写 `user_id`** → 位移永远无法去重(重导入 791 条变 1582 条),
|
||
且下次启动时迁移的回填 UPDATE 会撞上 `idx_movements_dedupe`,**整个站点起不来**
|
||
(`SQLSTATE 23505`,实测复现)。已补 user_id + `ON CONFLICT DO NOTHING`,
|
||
并把迁移里三个回填 UPDATE 各自包进 `EXCEPTION WHEN unique_violation`,保证迁移再也不会拖垮启动。
|
||
|
||
### 数据集模型:已定「快照式」并落地(用户在两个方向里选了快照式)
|
||
「自然键跨数据集全局去重」与「一次上传 = 一份完整数据集」互相矛盾:全局去重下,更新备份里的
|
||
新记录只会落进未激活的数据集,页面上完全看不到(已实测:删 1 条后重导,新记录进了
|
||
`is_active=f` 的数据集 #2,页面仍显示 822 条)。
|
||
|
||
最终实现(快照式 B+):
|
||
- 一份备份 = 一份完整快照,行级唯一性只靠各表自带的 `UNIQUE (dataset_id, src_pk)`
|
||
- `schema.sql`:`DROP INDEX idx_visits/movements/weather_dedupe`(迁移里清理旧索引),
|
||
`datasets` 加 `content_hash` 并建 `(user_id, content_hash)` 索引
|
||
- `ingest.Import`:先按 `contentHash(b)`(到访自然键排序后 sha256)查重,命中就复用旧数据集
|
||
并返回 `Stats.Identical=true`;否则建新快照,最后 `UPDATE datasets SET is_active=(id=$1) WHERE user_id=$2`
|
||
让最新快照接管展示
|
||
- `handlers_admin.go`:同 SHA 重复上传改为「已导入过,未重复导入」并顺手删掉刚落盘的文件
|
||
(顺带修了删除数据集不删上传文件的 P2);提示语明确写「已切换为当前展示」
|
||
- 回归全绿(一次性库实测):首导 823 / 同文件复用 / 内容同字节不同的复用 / 含 1 条新到访的
|
||
备份 → 新快照 #2 824 条接管展示,页面上新记录可见
|
||
- 已知小尾巴:存量数据集的 `content_hash` 是 NULL,无法识别与它的内容重复,只影响第一次
|
||
重传;后续上传正常
|
||
- 交叉编译产物 `dist/rond-linux-amd64` 已同步重编
|
||
|
||
### 回归验证配方(可复用,别动真实库)
|
||
1. 建一次性库:`CREATE DATABASE rond_dedup_test`
|
||
2. 写 `conf/app.test.ini` 指向它、`listen = :8090`、独立 upload/data 目录
|
||
3. 首次启动自动建表并生成 `admin / rond-admin`
|
||
4. `curl -X POST -d "username=admin&password=rond-admin" .../admin/login` 拿 cookie
|
||
5. `curl -b <jar> -F "[email protected]" .../admin/upload`,提示语在 303 的
|
||
`Location` 头里(URL 编码,`urllib.parse.unquote` 解一下)
|
||
6. 造「内容相同但摘要不同」的备份:用 python `zipfile` 按原条目重打包即可换 SHA
|
||
7. 收尾:kill rond.exe → `DROP DATABASE` → 删 `conf/app.test.ini` 与测试目录
|
||
|
||
### 其他备忘
|
||
- `go build ... | head -20 && echo OK` 会**掩盖编译失败**(管道退出码来自 head),别这么判成功
|
||
- Windows 上用 python 写 `/tmp/x` 会落到 `C:\tmp`(和 Git Bash 的 /tmp 不是一处),
|
||
尽量写项目内路径
|
||
- 后台删除数据集只删 DB 行,`storage/uploads/` 里的原始文件会留在磁盘上(P2,待清理逻辑)
|
||
|
||
### 世界迷雾叠加(已全部落地并验证)
|
||
- `internal/fog`(fog.go 解码/编码、store.go 内存索引+Import(merge)、render.go 瓦片渲染)
|
||
- 端到端:Go 解码与 Python 原型一致(52 tile / 8701 块 / 575753 格),编码回环无损(299112B)
|
||
- 路由:`POST /admin/fog`(mode=overlay|cover)、`GET /admin/fog/export`、`GET /tiles/fog/{z}/{x}/{y}?crs=`
|
||
- 前端:mapConfig 下发 fog 统计,rond-map.js 图层控件加「世界迷雾」,切底图自动换 crs 重拉
|
||
- 渲染两坑:① 低缩放级按全球块范围双循环 = z0 卡死 43 亿次 → 改为遍历块表+粗裁剪
|
||
② `image.RGBA` 是预乘 alpha,直写颜色被 png 编码器除回 alpha 变绿 → 用 `image.NRGBA`
|
||
- 对齐验证:足迹点 WGS 格位图已点亮;gcj02 渲染像素与足迹点像素偏差 0.0px(数学);
|
||
z15 近景合成图迷雾沿道路分布、红点落在迷雾格上(视觉)
|
||
- 测试:overlay 删块恢复 ✓、cover 清空重导 ✓、导出→再导入格数不变 ✓
|
||
- 测试配置留在 `conf/app-test.ini`(已 gitignore);主站 8080 还是旧二进制,重启后才有迷雾功能
|
||
- 19:07 主站已用新二进制重启(后台任务),真实库迁移出 fog_blocks ✓,fog 瓦片/配置接口正常;
|
||
真实库尚未导入迷雾,等用户在后台传 .fwss
|
||
- 整体检查:build/vet 零问题;仓库历史文件是 CRLF 行尾(gofmt 全文件 diff),只有 internal/fog
|
||
做了 gofmt;fog.go 里多余的 filepath_Base 已换成 filepath.Base
|
||
|
||
### P1+P2 六个功能(19:18-19:38 全部落地并冒烟通过)
|
||
- 迷雾覆盖统计:fog.CellOf/AreaKm2/Index.CellLit + web/fogCoverage,stats 页新区块;
|
||
坑:SQL 少写一列但 Scan 五个目标 → 静默返回 nil(区块不显示),已修
|
||
- 行程轨迹:/api/track(movements+places 起终点,5000 段上限),map.html 行程轨迹开关,
|
||
rond-map.js setTrack,随底图坐标系重投影
|
||
- 到访热力:vendor leaflet-heat.js(unpkg 0.2.0),map.html 热力开关 + setHeat,权重=到访次数
|
||
- 年度报告:/report?y=,Nav 新增「报告」,report.html(KPI+城市榜+南北两端+交通)
|
||
- 数据导出:/admin/export/places.{geojson,gpx},全量地点含家/工作(站长本人数据),
|
||
GCJ-02 原样导出并在 properties 注明 crs
|
||
- PWA:manifest.webmanifest + PIL 生成的爪印图标 192/512 + layout head meta
|
||
- 验证:测试库(rond_exp_test,已删)验导出 323 features/323 wpt、迷雾覆盖 47.8km²、
|
||
河池 43/93 等;主站 6 条路由全 200
|
||
- 所有 Go 文件已 gofmt(含 LF 行尾归一,为将来 git init 首提交做准备)
|
||
|
||
### 三个增强功能(20:00-20:45 全部落地并验证,主站 8080 已用最终二进制重启)
|
||
- **OSM 免密钥兜底**:高德瓦片 tileerror≥8 次前端自动切 OSM + toast; clarification:Leaflet 是渲染库
|
||
不是瓦片源,高德本来就是免 key 直连默认底图
|
||
- **公开页面开关**:settings 保存 `pages`(map/places/timeline/stats/report),guardPage 中间件
|
||
对匿名访客 404,管理员放行,导航同步隐藏;实测 anon /stats=404、admin /stats=200
|
||
- **TOTP 两步验证**(internal/auth/totp.go + handlers_admin.go):RFC 6238 HMAC-SHA1 30s ±1 窗口;
|
||
两步登录中间令牌 `2fa|uid|exp|mac`(绑定口令摘要,改密失效,5 分钟);关闭 2FA 也要求新鲜验证码。
|
||
全流程实测通过:绑定→确认→登出→密码登录→动态码→/admin 200;负例(错码/篡改令牌)均被拒;
|
||
关闭后登录免第二步 ✓
|
||
- **两个坑**:① TOTP 计数器曾用 `t.Unix()/int64(30*time.Second)`(除以 300 亿),改 `unixSec/30`;
|
||
② login2FA 曾用 `SplitN(pending,"|",2)[0]` 取 uid(取到的是 "2fa" 前缀),改 `parts[1]`
|
||
- **测试方法坑(重要)**:html/template 会把属性值里的 `+` 转义成 `+`(防 UTF-7),curl 从 HTML
|
||
抠隐藏字段直接回传会验签失败——浏览器会解码实体,这不是产品 bug。测试脚本要先 `sed 's/+/+/g'`
|
||
- 验证用测试账号:首次启动自动生成 admin/rond-admin(README 有写)
|
||
- 清理:rond_2fa_test 库已 DROP、conf/app-2fa.ini 与 .tmp-test/2fa 已删;conf/app-test.ini 保留
|
||
(gitignored,回归配方用)
|
||
- venv 的 python.exe 在 `envs/<name>/Scripts/python.exe`(不在根目录),用户记忆里写的 sss 环境可用
|
||
|
||
|
||
### 口令重置(21:05)
|
||
- 主站真实库(rond_with_you)的 admin 口令早已改过,默认 rond-admin 只对空表新库生效
|
||
(EnsureDefaultUser 见 users 非空即跳过);用户忘了旧口令,用项目内 auth.HashPassword 写了一次性
|
||
重置程序(.tmp-test/resetpw,用后已删)把口令恢复为 rond-admin,curl 实测登录 303→/admin 200 ✓
|
||
- 改口令会同时让旧会话失效(session MAC 混入口令摘要前缀)——实测无异常
|
||
- 遗留建议(P2,未实施,等批准):默认账号首次登录时页面没有任何「请修改默认口令」的提示,
|
||
README 有写但站点不强制;可考虑 EnsureDefaultUser 建的账号加个首登 flash 提示
|
||
|
||
### 默认口令警示 + 迷雾后台管理增强(22:30-22:45,主站已重启生效)
|
||
- adminHome 检测 admin 口令仍为 rond-admin 时,后台首页顶部渲染警示条(含改密/2FA 链接);
|
||
实现:AdminData.DefaultPW = auth.VerifyPassword(p.User.Hash, "rond-admin"),仅后台首页每次渲染时验证一次
|
||
- 迷雾卡片增强:空态引导(尚未导入提示)、块/格/估算面积/最近更新时间(fog_blocks.max(updated_at),
|
||
sql.NullTime + 模板函数 dtt 接受 *time.Time)、「清空迷雾」按钮(POST /admin/fog/clear,confirm 后
|
||
DELETE FROM fog_blocks + fogResetIndex() 换掉内存单例索引)
|
||
- 模板函数注意:text/template 调函数时指针参数不会自动解引用,可空时间字段要么加 *T 版本函数,
|
||
要么模板里 if 判空后用 deref
|
||
- 安全全链路实测:导出(299112B)→清空→空态→cover 重导→8701 块/575753 格/47.8km² 完整还原,瓦片 200
|
||
- 用户真实库迷雾是用户 22:26 自己在后台导入的(说明迷雾 UI 其实可用,只是缺状态展示让人困惑)
|
||
|
||
### 迷雾可视化 A+C + 传输层性能优化(23:50-00:25,主站已重启生效)
|
||
- 迷雾配色改高对比:填充 #307ae0 a=132、边界 #103484 a=232;render.go 改为两遍渲染
|
||
(先填 mask,再按四邻域判定填充/描边),瓦片外邻格按「已探索」处理以免接缝处出现网格伪影。
|
||
实测贵阳 z12 瓦片:填充 5572px / 轮廓 663px ✓
|
||
- 前端加「迷雾浓度」滑杆(L.Control + localStorage rond.fogOpacity,默认沿用图层 opacity 0.9)
|
||
- 性能:新增 internal/web/gzip.go(gzip 池 + 首字节判 content-type,PNG 透传);
|
||
assets.go 计算静态文件哈希作 assetVersion,cacheStatic 对 ?v=匹配者给 immutable 一年;
|
||
/map 不再内联 points(58.6KB→12.5KB,gzip 3.1KB)改走 /api/points;leaflet-heat 改为
|
||
首次勾选热力图时动态加载(ensureHeat)
|
||
- 实测:/stats 38.3→5.4KB、/api/track 38.9→6.7KB、/report 6.3→2.0KB
|
||
- 坑:模板函数传 *time.Time 不会自动解引用(另见上条);server.go 里 gzip 是包级函数不是 Server 方法
|
||
|
||
### 访客可见区域白名单 + 地点别名/备注(01:00-01:30,主站已重启生效)
|
||
- 区域白名单:setting.Settings.Regions(省/市/区任意层级);stats.Filter.Regions 在 visitsWhere 里
|
||
生成三段 IN 条件(province/city/district 各一份占位符);filterOf 里仅 `!p.IsAdmin()` 时注入,
|
||
因此地图/地点库/时间线/统计/报告全站生效、管理员全量。
|
||
实测:设「贵阳市」→ 匿名 73 点全为贵阳,管理员 283 点 ✓(测完已清空)
|
||
- 地点备注:新表 place_notes(user_id, src_pk, alias, note),按 src_pk 而非 places.id 存,
|
||
重传备份不丢;internal/notes 包(All/Save,空则删记录)。Place 加 SrcPK/Alias/Note 三个字段,
|
||
placeCols 末尾追加 p.src_pk(scanPlace 同步)
|
||
- 显示约定:别名对外替代原名(applyNotes 里直接改 Name,各页面/地图气泡自动生效),
|
||
备注仅管理员可见(applyNotes 传 admin 标志)
|
||
- 坑:applyNotes 传切片,单地点场景必须 `ps := []stats.Place{place}; ...; place = ps[0]`,
|
||
直接传字面量切片改不到原值
|
||
- 后台设置页新增「访客可见区域」textarea(一行一个),保存时按行 trim 去空
|
||
|
||
### 备注可见性开关 + 后台备注管理页(01:25-01:35,主站已重启生效)
|
||
- setting.Settings.NotesPublic(notes_public,默认 false);applyNotes 参数由 admin 改为 showNote
|
||
= p.IsAdmin() || p.Settings.NotesPublic,别名始终对外、备注按开关
|
||
- 新增 GET /admin/notes(notesPage + templates/admin/notes.html):LEFT JOIN places 取地点名/城市/到访数,
|
||
支持 ?q= 搜索(别名/备注/地点名 ILIKE),每行就地保存/删除(删除=提交空值,Save 会自动删记录),
|
||
按 Referer 判断保存后回管理页还是后台首页
|
||
- 后台首页导航与地点详情页都已挂入口
|
||
- **事故与修复**:用 curl 单字段 POST /admin/settings 测区域白名单时,未提交 pages 字段导致
|
||
「公开页面」被清空(/map 等全部 404)。教训:settingsSubmit 是整体覆盖,任何脚本化测试都必须
|
||
把 pages/modules 等字段一并回传;已用全字段 POST 恢复
|
||
- Git Bash 里 `curl -o /dev/null` 偶发 exit 23(写入失败),改成 -o 文件更稳
|
||
|
||
### 四个增强功能 F1–F4(20:5x 收尾,主站已重启实测)
|
||
- F1 出行方式配色:apiTrack 返回 `modes` 图例(空方式归「步行/其他」灰色 #8e8e93),
|
||
rond-map.js 渲染图例;实测 `modes:[步行/其他 370, 电🐔 317, 地铁 22, 高铁 21, 公交 17, 火车 9]`
|
||
- F2 城市级聚合 + 首次到达里程碑:
|
||
- 地图 `/api/cities` 按城市聚合到访/时长/首次(last)日期,圈大小随到访量;已剔除家/工作
|
||
- 报告页「🏅 首次到达的城市」里程碑:firstArrivalCities 查「有史以来首次到访落在本年」的城市
|
||
(HAVING min(arrival) in [from,to)),按日期升序;区域白名单对访客同样生效
|
||
- **实测发现并修复的 bug**:apiCityAgg 原 SQL 写 `AND NOT p.is_home AND NOT p.is_work`,
|
||
但 is_home/is_work 是 visits 列、places 表没有 → `SQLSTATE 42703` 直接 500。
|
||
改为 `NOT EXISTS (SELECT 1 FROM visits vh WHERE vh.place_id=p.id AND (vh.is_home OR vh.is_work))`
|
||
- 报告页已验证 2025 年出现里程碑、/api/cities 返回 9 城带 first/last 日期
|
||
- F3 年度报告长图/PDF 分享:ReportData 加 Cities []CityMilestone;报告页加「复制链接」(`navigator.share`
|
||
优先、否则 clipboard) + 「保存为 PDF」(`window.print()`),app.css 加 `@media print` 隐藏导航/页脚/按钮、
|
||
卡片 break-inside:avoid。注:长图用浏览器打印生成 PDF(未接 html2canvas),README 已注明该取舍
|
||
- F4 从 GPX 补充轨迹:internal/gpx 解析 trk/trkseg/rte(WGS-84);adminGpxUpload 存 gpx_tracks,
|
||
apiGpx 按 crs=gcj02 把 WGS-84 转 GCJ-02 对齐高德底图;地图橙色叠加
|
||
- **修复**:gpx.Parse 原来 `if len(out)>0 return` 在已有 trk 时直接返回、丢掉 rte;改为 trk 与 rte 都追加
|
||
- 实测:登录 admin/rond-admin → 上传含 trk+rte 的测试 gpx → /api/gpx 返回两条轨迹(测试数据已删除)
|
||
- 验证手段:`go build` + `go vet` 全过;主站后台起、curl 实测各 API 与报告页;测试轨迹上传后清理
|
||
- README 已把 F1–F4 从「后续可以做的」挪到已实现章节,并补 GPX/城市聚合/报告分享说明
|