zhouruizhe
main
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
微信主包上限 2 MB,30 张 800×600 照片单独就 2.6 MB, 整包 3.2 MB,上传被拒(错误码 80051)。 按使用场景把照片拆成两层: - 主包缩略图 400×300 q75(678 KB),供地图、行程、打卡卡片使用, 这些场景最大只显示 192rpx(≈288 px @DPR3),800×600 是过剩 - 分包大图 800×600 q66(1832 KB),供详情页 hero 使用, 随 pages-poi 分包按需下载 两层都保持 4:3,PoiImage 的 aspectFill 行为不变,视觉表现与之前一致。 详情页从 pages/poi/detail 移到 pages-poi/detail:主包页面无法引用 分包资源,hero 要用大图,页面就必须在分包内。新增 coverPhotoFullUrlFor() 供分包内页面取大图,占位图仍指向主包。 verify-weixin-output.mjs 增加防回归检查:分包注册、两层照片数量 一致、主包与各分包实际体积(留 64 KB 余量)。包体再超限会在 verify 阶段失败,不必等上传才发现。 process-poi-photos.mjs 重写为双层产出,幂等,末尾报告包体占用并 在超限时退出非零。原图改从 src/photo-intake/ 读取(不提交仓库)。 改造后:主包 1522 KB、分包 pages-poi 1847 KB,均在 2048 KB 内。 mp-weixin 与 H5 均编译通过,97 个测试通过,vue-tsc 与 ESLint 无错。
三个问题,前两个各有独立根因。 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。
f8ad5e1
选中标点后地图在左右/上下反复抽动,根因是视口回写形成了自激回路: map 的 longitude/latitude/scale 绑定到 store,而 regionchange 又无条件把 地图当前中心点写回 store —— 写 store 触发地图移动,移动结束回传一个 「差一点点」的中心点,再写回,再移动。上一个提交把中心点改成从 detail.centerLocation 同步读取后,回路里原本靠 getCenterLocation 异步跳变 掩盖住的这一点噪声就直接闭合了。 两道闸: - 只接受手势造成的变化。causedBy 为 update(我们自己改绑定值或调 includePoints 触发)时 store 已是权威值,不回写。老基础库拿不到 causedBy 时退化到下一道闸。 - 所有回写走 commitViewport,经 isSignificantViewportChange 过滤掉小于 1e-4 度 / 0.01 级的变化。远小于任何一次真实拖动,足以吸收量化噪声。 顺带修一个 H5 构建回归(1bcdd40 引入):uni 的 H5 路由生成器按路径推导 组件标识,pages/poi/detail 与 pages-poi/detail 都归一成 PagesPoiDetail, 重复声明导致 build:h5 失败。兼容跳板必须留在旧路径上,所以改名分包路由 pages-poi/detail -> pages-poi/poi-detail。
本机没装 git-lfs,仓库里留下的是 130 字节的 LFS 指针而不是文档本体, 对代码和构建都没有作用。按需要直接从工作树移除。 .gitattributes 里的 LFS 规则保留,它约束的是以后新增的二进制文件。
我已经阅读了完整的 diff、实际的源码文件以及项目的约定。这是审查结论。
本次 PR 主体是三件事:① POI 详情页移入 pages-poi 分包 + 照片分两层(主包缩略图 / 分包大图)以躲开微信 2 MB 主包上限;② 收敛地图 regionchange 回写回路,修复选中标点后地图抽动;③ 统一 (0,0) Null-Island 坐标的拒绝逻辑。代码注释详尽、思路清晰,并配套了 verify-weixin-output.mjs 产物校验与两个 vitest 用例。其余 files/ 下 58 个删除是归档/打卡旧代码清理,属无害改动。
pages-poi
regionchange
(0,0)
verify-weixin-output.mjs
files/
commitViewport
isSignificantViewportChange
causedBy
src/pages/map/index.vue:341
isTrustworthyCoordinate
src/domain/poi/validation.ts
pages/poi/detail
pages-poi/poi-detail
scripts/process-poi-photos.mjs:1
import { existsSync } from 'node:fs'
import
scripts/process-poi-photos.mjs
MAIN_PACKAGE_LIMIT_KB = 2048
thumb.kb >= MAIN_PACKAGE_LIMIT_KB
mainPackageKb > 1984
src/pages-poi/poi-detail.vue:24
heroImages
coverImageId
images
src/pages.json
\ No newline at end of file
src/pages/poi/detail.vue:29
redirectTo
rawPoiId
encodeURIComponent
onLoad
decodeURIComponent
poi_*
%
test/map-viewport.test.ts
test/map-store.test.ts
node_modules
vitest
coverPhotoFullUrlFor
/pages-poi/static/photos/<id>.jpg
src/data/poi/photos.ts:73
regionchange end
navigating
enable-scroll/enable-zoom=false
selectMarker
src/pages/map/index.vue:246
:662
pages/poi/detail?poiId=xxx
No dependencies set.
The note is not visible to the blocked user.
我已经阅读了完整的 diff、实际的源码文件以及项目的约定。这是审查结论。
🔍 审查结论
本次 PR 主体是三件事:① POI 详情页移入
pages-poi分包 + 照片分两层(主包缩略图 / 分包大图)以躲开微信 2 MB 主包上限;② 收敛地图regionchange回写回路,修复选中标点后地图抽动;③ 统一(0,0)Null-Island 坐标的拒绝逻辑。代码注释详尽、思路清晰,并配套了verify-weixin-output.mjs产物校验与两个 vitest 用例。其余files/下 58 个删除是归档/打卡旧代码清理,属无害改动。严重问题(必须修复)
commitViewport→isSignificantViewportChange的阈值门 +causedBy过滤(src/pages/map/index.vue:341)确实能切断「写 store → 地图动 → regionchange → 写 store」的回路;isTrustworthyCoordinate(src/domain/poi/validation.ts)在 validation / location store / location service / map 页四处复用且行为一致;旧路径pages/poi/detail降级为 redirectTo 跳板,且所有调用方(map/assistant/itinerary/check-in)均已改指pages-poi/poi-detail,无遗漏。建议改进
scripts/process-poi-photos.mjs:1的import { existsSync } from 'node:fs'写在了文件顶部文档注释之前(注释从第 2 行才开始)。属纯风格问题,建议把这条 import 挪到注释块之后、与其余import合并,符合本文件其它 import 的排布习惯。scripts/process-poi-photos.mjs里MAIN_PACKAGE_LIMIT_KB = 2048对「主包缩略图」做超限判断(thumb.kb >= MAIN_PACKAGE_LIMIT_KB)语义偏松:缩略图与 JS/CSS/其它静态资源共用主包 2 MB 预算,单看缩略图没超 2 MB 并不代表整体安全。真正的兜底是verify-weixin-output.mjs里对整包mainPackageKb > 1984的检查,这里不会出 bug,但建议把脚本里的提示文案 / 阈值与「整包」口径对齐,避免误导后人以为缩略图自身可达 2 MB。src/pages-poi/poi-detail.vue:24(heroImagescomputed)只把coverImageId对应那张图替换成分包大图,其余图片仍用主包 400×300 缩略图。若某 POI 的images有多张,hero 画廊里非封面帧会被放大到 750×422rpx 出现明显糊感/质量跳变。当前 POI 数据若普遍只有一张封面图则无影响;建议确认数据形态,多图时要么全部走大图、要么只展示封面单图。src/pages.json末尾无换行(diff 末行\ No newline at end of file)。与其它 JSON 配置风格不一致,建议补一个尾换行。src/pages/poi/detail.vue:29跳板redirectTo时对rawPoiId做了encodeURIComponent,而新详情页onLoad又对 query 取值做了decodeURIComponent。由于现有 poiId 均为 ASCII(poi_*),编解码是恒等无副作用;但这是「编码 → 解码 → 再编码 → 再解码」的两段链路,若日后 poiId 出现%/ 中文等字符会被双重解码出错。非当前阻塞,记录为潜在脆弱点。测试与验证建议
test/map-viewport.test.ts与test/map-store.test.ts三个用例(Null-Island 拒绝、reset 兜底、阈值门)覆盖到位。本机当前无node_modules,CI 里需确认vitest能跑通。coverPhotoFullUrlFor返回/pages-poi/static/photos/<id>.jpg(src/data/poi/photos.ts:73),需在微信开发者工具 + 真机确认分包页面能正确按需加载该路径(分包未下载时不应被主包页面引用)。verify-weixin-output.mjs只校验了文件存在与两层张数一致,校验不了运行时 src 解析。pages-poi分包均未触顶(脚本设了 1984 KB 安全线,但真机上传才是最终判据)。regionchange end回写 → 观察地图是否仍反复微动;并验证拖动后返回页面能恢复到用户拖到的位置(确认commitViewport没有把真实拖动误判为噪声丢弃)。navigating期间enable-scroll/enable-zoom=false、selectMarker提前返回(src/pages/map/index.vue:246、:662附近),手测点击标点跳详情、再快速点打卡记录入口的连点场景,确认无重复入栈/白屏。pages/poi/detail?poiId=xxx的入口(模拟已发出的分享卡 / 模拟器上次停留路由)冷启动,确认经redirectTo落到新详情页而非白屏。