forked from zhouruizhe/gmTouringMiniApp
三个问题,前两个各有独立根因。
1) 首次打开定位到几内亚湾、底图变成 HERE
regionchange 处理里读的是 `event.detail.longitude`,但微信的 regionchange
载荷没有这个字段,`Number(undefined)` 恒为 NaN,于是每次都落到异步的
getCenterLocation。冷启动时地图 SDK 还没拿到有效中心点,它会回传 (0, 0),
而两个 store 的坐标校验只查 Number.isFinite,(0, 0) 直接通过。
(0, 0) 落在几内亚湾(Null Island),微信 <map> 一到境外坐标就切 HERE 底图。
全程不需要用户点过定位按钮。
数据集校验器本来就在拒绝零坐标,只是运行时 store 没套用同一条规则。现把它
提成共享守卫 isTrustworthyCoordinate,validateCoordinates 改为复用,并铺到
map store、location store 和打卡定位服务。regionchange 一侧改为优先读微信
真正给的 detail.centerLocation,回落路径校验后才写入,且 mapReady 为 false
时不接受任何回写。
2) 冷启动白屏、左上角只剩回首页的小房子
f8ad5e1 把详情页从 pages/poi/detail 移进 pages-poi 分包,源码调用点都改了,
但旧路由本身从 app.json 消失。任何还攥着旧路径的入口 —— 开发者工具模拟器上次
停留的路由、预览启动页、已发出的分享卡片或二维码 —— 冷启动会落到微信解析不出
的路由,渲染成白屏;因为不是 tabBar 页且栈深为 1,左上角只剩小房子。
旧路径补一个只做重定向的跳板页,带 poiId 就 redirectTo 新路径,不带就 reLaunch
回地图。用 redirectTo 是为了让跳板不留在页面栈里。主包 +1 KB。等所有入口都刷新
过可以删掉。
3) 跳转详情页时地图仍可拖动几毫秒
<map> 是渲染在 webview 之上的原生组件,销毁是异步的,页面转场开始了它还在。
navigating 之前只用于防重复点击,没接到地图上。现在接上 enable-scroll /
enable-zoom,并给 selectMarker、openCheckInRecords 补同一个守卫(后者原先完全
没有防护),regionchange 在跳转期间也不再回写 viewport。onShow 里直接复位
navigating,返回时立刻恢复交互,不等 500ms 兜底定时器。
原生组件的异步销毁消不掉,但那几毫秒里地图不再响应拖动和缩放。
验证:测试 100 passed(map store 新增零坐标、越界、resetViewport 兜底用例),
type-check 干净。build 主包 1187 KB / 分包 1841 KB,dev 1527 KB / 1847 KB,
均过 verify:mp-weixin。
91 lines
3.4 KiB
TypeScript
91 lines
3.4 KiB
TypeScript
import { createPinia, setActivePinia } from 'pinia'
|
|
import { beforeEach, describe, expect, it } from 'vitest'
|
|
import { DEFAULT_GUANGMING_VIEWPORT, useLocationStore, useMapStore } from '@/stores'
|
|
|
|
describe('map session store', () => {
|
|
beforeEach(() => {
|
|
setActivePinia(createPinia())
|
|
})
|
|
|
|
it('keeps category, selected POI and viewport while navigating back', () => {
|
|
const store = useMapStore()
|
|
store.setCategory('urban_park')
|
|
store.selectPoi('poi_hongqiao_park')
|
|
store.updateViewport({ longitude: 113.94, latitude: 22.76, scale: 13 })
|
|
|
|
expect(store.categoryCode).toBe('urban_park')
|
|
expect(store.selectedPoiId).toBe('poi_hongqiao_park')
|
|
expect(store.viewport).toEqual({ longitude: 113.94, latitude: 22.76, scale: 13 })
|
|
})
|
|
|
|
it('shows and clears the planned-route overlay explicitly', () => {
|
|
const store = useMapStore()
|
|
expect(store.plannedRouteVisible).toBe(false)
|
|
store.showPlannedRoute()
|
|
expect(store.plannedRouteVisible).toBe(true)
|
|
store.hidePlannedRoute()
|
|
expect(store.plannedRouteVisible).toBe(false)
|
|
})
|
|
|
|
it('ignores invalid viewport updates', () => {
|
|
const store = useMapStore()
|
|
store.updateViewport({ longitude: Number.NaN, latitude: 22.76, scale: 13 })
|
|
expect(store.viewport).toEqual(DEFAULT_GUANGMING_VIEWPORT)
|
|
})
|
|
|
|
it('keeps a validated user location in memory independently from the map viewport', () => {
|
|
const mapStore = useMapStore()
|
|
const locationStore = useLocationStore()
|
|
|
|
expect(locationStore.updateLocation(113.94, 22.76, 18)).toBe(true)
|
|
expect(locationStore.snapshot).toMatchObject({
|
|
longitude: 113.94,
|
|
latitude: 22.76,
|
|
accuracy: 18,
|
|
coordinateSystem: 'GCJ02',
|
|
})
|
|
expect(locationStore.status).toBe('ready')
|
|
expect(mapStore.viewport).toEqual(DEFAULT_GUANGMING_VIEWPORT)
|
|
})
|
|
|
|
it('rejects malformed user coordinates', () => {
|
|
const store = useLocationStore()
|
|
expect(store.updateLocation(181, 22.76, 10)).toBe(false)
|
|
expect(store.snapshot).toBeNull()
|
|
})
|
|
|
|
// 定位接口降级 / 地图 SDK 还没拿到定位时会回传 (0, 0),
|
|
// 它落在几内亚湾,会把地图甩到非洲外海并触发境外底图。
|
|
it('rejects null-island coordinates for the map viewport', () => {
|
|
const store = useMapStore()
|
|
store.updateViewport({ longitude: 0, latitude: 0, scale: 15 })
|
|
expect(store.viewport).toEqual(DEFAULT_GUANGMING_VIEWPORT)
|
|
|
|
store.updateViewport({ longitude: 113.94, latitude: 0, scale: 15 })
|
|
expect(store.viewport).toEqual(DEFAULT_GUANGMING_VIEWPORT)
|
|
|
|
store.updateViewport({ longitude: 0, latitude: 22.76, scale: 15 })
|
|
expect(store.viewport).toEqual(DEFAULT_GUANGMING_VIEWPORT)
|
|
})
|
|
|
|
it('rejects null-island coordinates for the user location', () => {
|
|
const store = useLocationStore()
|
|
expect(store.updateLocation(0, 0, 10)).toBe(false)
|
|
expect(store.updateLocation(113.94, 0, 10)).toBe(false)
|
|
expect(store.updateLocation(0, 22.76, 10)).toBe(false)
|
|
expect(store.snapshot).toBeNull()
|
|
expect(store.status).toBe('idle')
|
|
})
|
|
|
|
it('falls back to the default viewport when reset is given an unusable one', () => {
|
|
const store = useMapStore()
|
|
store.updateViewport({ longitude: 113.94, latitude: 22.76, scale: 13 })
|
|
|
|
store.resetViewport({ longitude: 0, latitude: 0, scale: 11 })
|
|
expect(store.viewport).toEqual(DEFAULT_GUANGMING_VIEWPORT)
|
|
|
|
store.resetSession({ longitude: 0, latitude: 0, scale: 11 })
|
|
expect(store.viewport).toEqual(DEFAULT_GUANGMING_VIEWPORT)
|
|
})
|
|
})
|