跳转至

开发日志归档(v0.8.37 ~ v0.9.x)

归档自 development-log.md (v0.10.104 时拆分)。当前活跃迭代见 开发日志(当前活跃 v0.10.85+)。 版本范围:v0.8.37 (2026-05-21) ~ v0.9.x (2026-05-22) — 早期 UI / 抓取调度雏形


2026-05-22 v0.9.0 → v0.9.1 UI 改版 阶段一微调:导航分组 + 设置入口去重

本次改动(按用户反馈)

  • 日志 / 设置 移到导航栏底部:左侧导航分两组 —— 主导航(概览/任务/数据)在上, 次级导航(日志/设置)置底,再下面是全局开关。监控/配置类入口归到底部,主流程更聚焦。
  • 去掉顶部 header 的设置齿轮header-page.tsx 原有「搜索任务设置」齿轮(开独立设置 窗口)与侧边栏「设置」重复,已删除。设置统一走侧边栏。
  • 云端设置入口常驻cloud-data-sync.tsx 的同步设置齿轮原来仅在「云端同步开启」时 才显示,改为常驻可见 —— 未开启也能进去配置。

遇到的问题

  • pnpm build 成功,版本 0.9.1,改动文件 0 类型错误。

注意点

  • 约定:后续每次更新都递增 package.json 版本号。
  • 顶部 header 保留(账号/会员/版本/客服/帮助/广播),仅去掉重复的设置齿轮。

2026-05-22 v0.8.58 → v0.9.0 UI 改版 阶段一:左侧导航框架

背景

整体界面改版,分阶段进行。详见根目录 v2-UI改版说明.md。 本次为阶段一:搭新导航框架,把现有功能归位,保证可用。

本次改动

  • wxt.config.tsoutDirdist 改为 dist-v2 —— v2 构建到 dist-v2/chrome-mv3/, 旧版 dist/chrome-mv3/(v0.8.58)冻结保留。
  • 新增 src/sections/layout/main-layout.tsx:左侧导航(概览/任务/商家/数据/日志/设置)+ 右侧内容区 + 顶部条(官网抓取开关、云端同步)。吸收了原 page-main-view 的状态逻辑。
  • 新增 src/sections/overview/overview-view.tsx:概览页(商家数 / 官网已采集 / 待采集 / 日志数 四个统计卡)。
  • 新增 src/sections/data/data-view.tsx:数据页(官网/邮箱/手机三个子 tab,阶段一占位)。
  • src/entrypoints/main/App.tsxPageMainViewMainLayout
  • 现有组件归位(无改动):任务页=MainFilters、商家页=LocalDataView、 日志页=LogView、设置页=SettingsView
  • 新增根目录 v2-UI改版说明.md

遇到的问题

  • pnpm build 成功,版本 0.9.0,输出 dist-v2/chrome-mv3/,改动文件 0 类型错误。

注意点

  • page-main-view.tsx 暂保留未删(已不再被引用),后续阶段清理。
  • 「任务」页阶段一仍是现有的批量搜索 UI(MainFilters);阶段二替换为任务队列。
  • v2 与旧版共用同一 storage / IndexedDB,数据互通、不会丢。
  • 内容区高度用 calc(100vh - 52px) 估算(减顶部 header),如有偏差后续微调。

阶段一内调整(按用户反馈)

  • 商家并入数据:取消独立「商家」导航项;「数据」页改为 商家 / 官网 / 邮箱 / 手机 四个 tab,商家为默认 tab(复用 LocalDataView)。导航精简为 5 项。
  • 理由:官网/邮箱/手机本质是商家记录字段的切片,同处一地更合理。
  • 全局开关移到左下角:去掉右上角顶部条;「提取官网邮箱/社媒」「云端同步」两个全局 开关移到左侧导航栏底部,固定常驻、状态随时可见,内容区也更宽。
  • cloud-data-sync.tsx 改为紧凑竖排布局以适配侧边栏宽度。

2026-05-22 v0.8.57 → v0.8.58 官网抓取:状态/错误码捕获 + Cloudflare 5 秒盾

问题与分析(对应用户 5 点)

1. 能打开的网站却显示「无法访问」(如 palmerstonmedicalcentre.com) - 实测该站 HTTP 200,但有 2 次跳转、整站加载要 9~11 秒。 - 旧逻辑:标签页等 scrapeTimeout(10s) → 取不到 performance.responseStatus(0) → probeHttpStatus 再 fetch、8s 超时 → 站点要 11s → 8s 中止 → 返回 -1「无法访问」。 - 即超时 + 探测超时双双短于站点加载时间 → 误判。

2. 开了官网/社媒采集后地图请求变慢 —— 资源竞争(无代码改动) - 官网抓取并发数=5 时,后台同时开 5 个真实标签页渲染完整网站(CPU/内存/带宽都吃)。 - 实开的地图页是重型 SPA,在 CPU 竞争下加载更慢 → 单位时间产出的翻页任务变少 → 「地图请求」增长变慢;翻页 fetch 也与网站加载抢带宽。 - 这是并发跑两套采集的固有代价。建议把「官网抓取并发数」调到 2~3 降低竞争。

3. 403 实为 Cloudflare「5 秒盾」 - 旧逻辑:注入脚本一见 Cloudflare 挑战页(title「just a moment」)就立即返回挑战页 HTML, 状态 403 —— 没等盾自动放行。

4 / 5. 证书错误 / 连接失败只显示「无法访问」,要具体错误码 - 旧逻辑 probeHttpStatus 失败统一返回 -1,拿不到 ERR_CERT_AUTHORITY_INVALIDERR_EMPTY_RESPONSE 等具体码(fetch 失败是不透明的 TypeError)。

改动

  • webRequest 捕获状态/错误码dynamic-scraper.ts):在模块顶层注册 webRequest.onCompleted(主框架 HTTP 状态码)与 onErrorOccurrednet::ERR_xxx 错误码)。顶层注册是 MV3 下可靠的关键(v0.8.52 曾因惰性注册而失效)。
  • 解决 #1:慢站点最终 onCompleted 时状态码被记下,标签页超时也能拿到真实 200。
  • 解决 #4/#5:证书错误、连接失败等由 onErrorOccurred 拿到具体 ERR_xxx
  • Cloudflare 5 秒盾dynamic-scraper.ts):抓到挑战页后,后台等 6s + 等重新加载完成, 重抓,最多 2 轮 —— 让盾自动放行后取到真实页面。
  • ScrapeResult 新增 error?PageLogEntry 新增 error?scraper-executor 透传; log-view 官网/社媒条目:有错误码时直接显示 ERR_xxx(红色,悬停看全)。

关于「无视证书错误」

  • 浏览器扩展没有 API 可以绕过 Chrome 的证书拦截页(标签页拦截页无法自动跳过, SW 的 fetch 也强制校验证书)。故只能「显示错误码」,无法「无视证书继续访问」。

遇到的问题

  • pnpm build 成功,版本 0.8.58,改动文件 0 类型错误。

注意点

  • 状态码优先级:页面 performance.responseStatus → webRequest onCompletedonErrorOccurred 错误码 → probeHttpStatus 兜底(-1)。
  • 真正「卡死无响应」的站点(如 calvary-act,连 25s 都不响应)在预算内拿不到错误码, 仍显示「无法访问」—— 属如实结果。
  • Cloudflare 站点单个最长约 36s(10s + 2×13s),仅该类站点变慢,占比小。

2026-05-22 v0.8.56 → v0.8.57 批次状态持久化 + SW 重启自动恢复

目标

解决 v0.8.56 注意点里说的局限:保活扛不住「电脑休眠」等导致的 SW 终止。 让 40 小时的长批次在 SW 被回收后能自动接回来。

做法

  • 持久化
  • startBatch 时把「任务清单 + 设置」写入 local:batchState(只写一次)。
  • publishProgress 时把「待处理翻页队列」写入 local:batchPaging(随进度刷新)。
  • 进度(status/finished)本就持续写在 local:batchProgress
  • stopBatch/finishBatch 时清除 batchState/batchPaging
  • 恢复:新增 restoreBatch(),在后台 SW 每次启动时调用:
  • batchState;若存在、且 batchProgress.status 是 running/paused/intercepted (说明上次批次没正常结束)→ 恢复内存态:
    • taskUrls/settingsbatchState 读回;
    • finishedCount 从进度读回,nextIndex = finishedCount(崩溃时在途未完成的实开 任务重做,重复数据由 deleteRepeat 去重兜底,不会丢任务);
    • 翻页队列从 batchPaging 读回;
    • closeHarvestWindow() 清掉 SW 回收前残留的孤儿标签页;
    • 若上次是 running → 自动 pump()/pumpPager() 续跑;paused/intercepted → 保持 暂停,等用户点「继续」。

涉及文件

  • src/entrypoints/background/batch-controller.ts:新增 BATCH_STATE_KEY/BATCH_PAGING_KEY 常量;publishProgress/startBatch/stopBatch/finishBatch 增持久化读写;新增导出 restoreBatch()
  • src/entrypoints/background/index.ts:SW 启动时调用 restoreBatch()

遇到的问题

  • pnpm build 成功,版本 0.8.57,改动文件 0 类型错误。

注意点

  • nextIndex 恢复成 finishedCount —— 崩溃瞬间正在「实开」的少数任务会重做一遍, 靠 googleId 去重,不会产生重复数据、也不会漏任务。
  • 翻页队列里「正在请求中」(非排队中)的任务,若 SW 恰好在它出队后、下次 publishProgress 前被回收,会丢失(该商家的第 2+ 页少量数据);属可接受的小概率损失。
  • batchState 含完整任务清单(约 1~2MB / 16031 条),storage.local 配额 10MB,足够; 且只在 startBatch 写一次。
  • 恢复是「自动」的:SW 一重启就接着跑;用户若不想继续,点「停止」即可。
  • 至此长批次可扛住:SW 空闲回收、扩展重载、电脑休眠后唤醒 —— 只要浏览器还在、批次没被 手动停止,就会自动续跑。

2026-05-22 v0.8.55 → v0.8.56 复查修复:SW 保活 + 去重邮箱丢失 bug

复查发现的问题

1. MV3 service worker 被终止 → 批次静默死亡(严重) - 批次的全部状态(taskUrls / nextIndex / pagingQueue / pagerActive / status…)都在 batch-controller.ts 的模块级变量里。 - MV3 的 service worker 空闲约 30s 就被浏览器终止;终止后这些变量全部丢失。 - 后果:暂停时间稍长、或运行中出现较长空窗,SW 一死,批次就没了 —— 点「继续」时 resumeBatch 看到的是重新初始化的 status='idle',直接 no-op,批次再也起不来。 16031 个任务约 40 小时,期间 SW 几乎必然被回收过。 - 修复:批次运行/暂停期间启动「保活」—— 每 20s 调一次 runtime.getPlatformInfo() 重置 SW 空闲计时器;startBatch 开、stopBatch/finishBatch 关。 - 局限:保活能扛住暂停和普通空窗,但扛不住「电脑休眠」。彻底方案是把批次状态持久化到 storage、SW 重启时恢复(改动较大,留作后续)。

2. 去重路径把邮箱写成了 undefined(数据 bug) - scraper-executor.ts 去重分支:emails: sourceRow.email —— 字段名应为 emails (复数,数组列),sourceRow.email 永远是 undefined。 - 后果:当一个官网此前已被其它商家抓过,命中去重时,社媒/whatsapp 正常复制,但 邮箱被写成 undefined(丢失)。 - 修复:sourceRow.emailsourceRow.emails(本就是历史遗留 bug,非本轮引入)。

复查确认无误的点

  • 暂停/继续的调度代码(pause/resume/pump/pumpPager/runPagingJob)逻辑正确,无冻结 bug。
  • Q2 状态码探测只在失败路径触发,成功抓取不受影响。
  • finalizeTabtabs.onRemoved 不会重复处理(先 tabs.delete 再关标签页)。
  • 多个翻页任务同时被拦截时,onInterception 只会弹一个验证页。

涉及文件

  • src/entrypoints/background/batch-controller.ts:新增 SW 保活(startKeepAlive/ stopKeepAlive)。
  • src/utils/scraper-executor.ts:去重邮箱字段名修正。

遇到的问题

  • pnpm build 成功,版本 0.8.56,改动文件 0 类型错误。

注意点

  • 保活靠 setInterval + 扩展 API 调用,是 MV3 社区通用做法;SW 存活期间持续生效。
  • 真正完备的做法是状态持久化 + 重启恢复,本次未做,长批次跨电脑休眠仍可能丢失。

2026-05-22 v0.8.54 → v0.8.55 官网超时可配置 + 状态码探测 + 翻页带会话

本次改动(对应用户 4 点)

  1. 采集速度分析(无代码改动):瓶颈在「实开」—— 每个实开要真实打开谷歌地图(重型 SPA), 后台标签页约 7~9s/个,且「并发实开数」默认 1 是串行。翻页是后台 fetch、很快,不是瓶颈。 提速主要靠调高「并发实开数」(2~3),但封号风险上升。
  2. 官网日志状态码:标签页取不到状态码时(页面没渲染出来),改为再 fetch 探测一次拿到 真实 HTTP 码;网络层失败记 -1,日志显示「无法访问」;0 显示「未知」。「失败」二字取消。
  3. 官网抓取超时可配置:原写死 10s,新增设置项 scrapeTimeout(5-60s,默认 10)。
  4. 翻页 fetch 改带会话fetchPagecredentials:'omit' 改为 'include'

第 4 点分析(暂停/继续后翻页不动)—— 复查修正

  • 复查结论:暂停/继续的调度代码本身没有冻结 bug。 逐行追踪 pauseBatch/resumeBatch/ pumpPager/runPagingJob:恢复后 pump 开实开、pumpPager 取队列、在途翻页任务 while(isHalted) 退出继续、新实开经 enqueuePaging 入队 —— 实开与翻页都能恢复。
  • 真正原因是翻页 fetch 被 Google 限流/拦截:原 credentials:'omit'(匿名无 cookie)。
  • 翻页 URL 由第 1 页 URL 构造,pb 里带的是登录会话的 token;却不带 cookie 发出 → token 与身份不一致 → Google 更易判为异常、限流。
  • 「后台翻页并发数」调到 5 + 间隔低至 1s 时更快触发。被限流后返回 /sorry/ 或非数据页 → 解析为 0 → 任务静默结束、日志无新增。
  • 被拦截后人机验证在「真实标签页」里完成(cookie 更新),匿名 fetch 拿不到 → 继续后又被拦 → 翻页卡死;而实开用真实带 cookie 标签页,验证后能恢复 → 表现为「实开动、翻页不动」。
  • 修复:fetchPagecredentials:'include' —— 与实开同一登录身份、token 与 cookie 一致, 额度更高、验证后可恢复。
  • 复查另发现并修复:enqueuePaging 原来在 status!=='running' 时直接丢弃任务,导致暂停期间 完成的实开任务的翻页任务被丢。改为仅在 status==='idle'(已停止)才丢弃,暂停/拦截期间 照常入队、恢复后处理。
  • 建议用户把「后台翻页并发数」调回 1~2、「翻页请求间隔」调回 2~5s,降低被限流概率。
  • 说明:限流是 Google 侧行为,无法在本地复现验证;以上为最合理推断,credentials:'include' 是依据「token/cookie 一致性」的最佳修复,仍需浏览器实测确认。

涉及文件

  • src/utils/storage-data.ts:新增 scrapeTimeout(默认 10)。
  • src/sections/settings/view/settings-view.tsx:新增「官网抓取超时」设置项 + 校验。
  • src/utils/dynamic-scraper.ts:超时改读设置;新增 probeHttpStatus,标签页取不到状态码 时 fetch 探测兜底。
  • src/entrypoints/background/batch-controller.tsfetchPagecredentials:'include'enqueuePaging 暂停期间改为入队而非丢弃。
  • src/sections/page/log-view.tsx:状态列支持 -1「无法访问」/ 0「未知」,列宽 50→64。

遇到的问题

  • pnpm build 成功,版本 0.8.55,改动文件 0 类型错误。

注意点

  • 翻页 fetch 现在会带用户的 Google cookie。账号本来就因「实开」(真实地图标签页)而暴露, 翻页带会话不增加新的暴露面,反而更稳。
  • 状态探测的 fetch 带 8s 超时(AbortController),避免卡住官网抓取队列。
  • 实开为何慢是「真实打开重型地图 SPA」的固有成本,非代码缺陷;并发是唯一的提速杠杆。

2026-05-22 v0.8.53 → v0.8.54 修复官网日志「失败」误判(HTTP 状态码取不到)

问题

  • 日志「官网/社媒」里大量条目显示「失败」,但这些网址实际能正常打开。
  • 实测 3 个被判「失败」的站点:actdayhospital.com.au / bartonspecialistclinic.com.au / morethanmedicine.com.au —— curl 全部 HTTP 200、1.7~4.6s 加载、有正常内容。

原因

  • 「失败」= 日志 status === 0。v0.8.53 用 webRequest.onCompleted 在后台 service worker 里抓标签页主框架状态码,写进全局 tabStatusMap
  • 该方式在 MV3 service worker 下不可靠:监听器是惰性注册(在 scrapeWithTab 内部、await 之后才 addListener),MV3 对运行时注册的 webRequest 监听存在时序/竞态问题,经常一次都没 触发 → tabStatusMap 取不到 → 返回 0 → 日志显示「失败」。
  • 实际抓取多数是成功的(HTML 拿到了、邮箱社媒也解析了),只是状态码这一列误判成「失败」。

改动

  • src/utils/dynamic-scraper.ts:彻底去掉 webRequest 监听与 tabStatusMap。改为在注入页面 的抓取脚本里直接读 performance.getEntriesByType('navigation')[0].responseStatus —— 这是 页面真实拿到的主文档 HTTP 状态码(含重定向后的最终状态),准确、无竞态、无 MV3 限制。 scrapeWithTab 注入函数返回 {html, status}

遇到的问题

  • pnpm build 成功,版本 0.8.54,改动文件 0 类型错误。

注意点

  • PerformanceNavigationTiming.responseStatus 需 Chrome 109+(现代 Chrome 均支持)。
  • 页面根本打不开时(chrome 错误页),executeScript 注入会抛错 → 仍记 status 0「失败」, 此时确属真实失败,符合预期。
  • 直接是社媒链接的条目不发 HTTP 请求,状态仍显示「-」。

2026-05-22 v0.8.52 → v0.8.53 0 条实开记录 + 设置精简重组 + 官网日志状态/结果列

本次改动(对应用户 5 点需求)

  1. 实开 0 条也记录startBatchSearch 重构为「无论从哪个分支退出,都记且只记一条 实开日志(含 0 条)」。点不到搜索按钮 / 无捕获 / 拦截 / 异常,统一记 0 条 + 落地 URL, 便于分析(如仅 1 个结果直接跳详情页的情况)。
  2. 删除无用设置waitTimeout(页面超时)、errorRetry(重试次数)全代码无引用 → 删除。scrollDelay 仅手动模式滚动兜底用 → 从设置移除,代码内固定 0.5s。
  3. 官网抓取延迟:新增 scrapeDelayMin/Max 设置(默认 1~3s),engine-manager 每个 官网抓取完成后按此随机间隔再抓下一个(原写死 300ms)。并发 deepScrapeConcurrency 本就存在(1-10),与地图采集完全独立。
  4. 设置界面重组:按「搜索设置 / 地图采集 / 官网·社媒采集 / 数据处理」四个区块分组, 每区块带标题;min/max 成对字段并排显示,更紧凑清晰。修复 searchCountry 失效 bug (main-filters 比较的是 'searchCode',而选项值是 iso2/name → 永远取国家全称)。
  5. 官网/社媒日志加列:新增 HTTP 状态码列(200/403/404…,0=网络错误显示「失败」, 按 2xx/3xx/4xx/5xx 着色);新增采集结果列(邮箱数量 + 社媒图标 + 电话/WhatsApp 图标)。

涉及文件

  • src/sections/content-button/index.tsxstartBatchSearchlogOpen 兜底;移除 scrollDelay
  • src/utils/storage-data.ts:删 scrollDelay/waitTimeout/errorRetry,加 scrapeDelayMin/MaxsearchCountry 默认改 'name',字段按区块重排。
  • src/utils/engine-manager.ts:新增 getScrapeDelayMs,官网抓取间隔改为可配置随机区间。
  • src/sections/page/main-filters.tsx:修复 searchCountry 比较值('searchCode''iso2')。
  • src/sections/settings/view/settings-view.tsx:整体重写为分组布局。
  • src/utils/page-log.tsPageLogEntrystatus/emails/phone/socials 字段。
  • src/utils/dynamic-scraper.ts:经 webRequest.onCompleted/onErrorOccurred 抓主框架 HTTP 状态码;scrapeWithTab 返回 {html, status};日志移到 executor。
  • src/utils/scraper-executor.ts:官网/社媒抓取日志带状态码与采集结果(成功失败都记一条)。
  • src/sections/page/log-view.tsx:官网/社媒子 tab 加状态列与采集结果列(图标)。

遇到的问题

  • searchCountry 一直只用国家全称:main-filterssearchCountry === 'searchCode', 而下拉值是 iso2/name,永远不命中 → 永远走 cn。已改为 === 'iso2',默认 'name' 保持原有效行为。
  • pnpm build 成功,版本 0.8.53,改动文件 0 类型错误。

注意点

  • v0.8.52 是连续开发中的中间版本,未单独测试、未单独备份;回滚基线为 backup/v0.8.51。 v0.8.53 已备份。
  • 官网 HTTP 状态码经 webRequest 抓标签页主框架响应,不额外发请求;网络错误/无法访问 记 0(日志显示「失败」)。直接是社媒链接的条目无 HTTP 请求,状态显示「-」。
  • 旧设置里的 scrollDelay/waitTimeout/errorRetry 残留无害,用户在设置页保存一次即清除。

2026-05-22 v0.8.51 → v0.8.52 实开/翻页解耦:翻页改后台 fetch(无标签页)

重大结论修正

  • 推翻 v0.8.40~42 的「后台 fetch 拿不到 /search 数据」结论。
  • 实测:用 curl(无 cookie、无会话、无浏览器,仅带 UA)GET /search?tbm=map&...&tch=1&pb=... → HTTP 200、150KB application/json、含完整商家数据。
  • /search 翻页接口完全无状态:给对 pb 参数就返回数据,不需要标签页、不需要登录。
  • 当年「失败」很可能是响应格式没对上(响应是含 )]}' 前缀的 JSON 包了一层数组, 而非裸 )]}'),被误判为「拿不到数据」。parseSearchData 本来就处理这种包裹格式。

本次改动(架构:实开 / 翻页 解耦,生产者 / 消费者)

  • 实开标签页(生产者):只负责开地图页、抓第 1 页链接、记「实开」日志, 第 1 页满 20 条就把 {第1页URL, 关键词} 交后台,然后立即关闭。不再在标签页里翻页。
  • 后台翻页(消费者):service worker 内直接 fetch() 第 2+ 页,解析、入库、记「请求」日志。 无标签页、无 cookie(credentials:'omit')。并发可配置(默认 1)。
  • 实开循环不再被翻页阻塞 → 实开间隔可压到很小,速度大幅提升。

涉及文件

  • src/entrypoints/background/batch-controller.ts:新增后台翻页队列 + 消费者(enqueuePaging/ pumpPager/runPagingJob/fetchPage);实开生命周期解耦(batch-done 抓完第 1 页即触发); 完成判定改为「实开做完 且 翻页队列空 且 无在途翻页」;新增 batchEpoch 防止换批后旧翻页任务串场。
  • src/sections/content-button/index.tsxstartBatchSearch 去掉本标签页翻页循环, 改为抓完第 1 页 → await 发送 batch-need-pagingreportBatchDone() 立即关闭。
  • src/entrypoints/background/index.ts:新增 batch-need-paging 消息处理。
  • src/sections/page/local-data-view.tsx:监听 maps-data-updated,后台翻页入库后刷新数量。
  • src/utils/storage-data.ts + settings-view.tsx + main-filters.tsx:新增「后台翻页并发数」 设置(pagerConcurrency,默认 1,可调 1-5)。

遇到的问题

  • 问题:tscstatus === 'paused' 比较「无重叠」(TS2367)。
  • 原因:status 是模块级可变状态,await 后会变;但 TS 按控制流把它收窄成了 'running'
  • 解决方案:加 isRunning()/isHalted() 取值函数,经函数读取绕开 TS 收窄。
  • 问题:末个任务的 batch-done 可能抢先于 batch-need-paging 处理 → 批量提前判定完成、翻页任务被丢。
  • 解决方案:content-button 里 awaitbatch-need-paging 发送后再 reportBatchDone()
  • pnpm build 成功,版本 0.8.52,改动文件 0 类型错误。

注意点

  • 进度条「已完成页面」现在统计的是实开任务数,会很快跑到 100%,但此时后台可能仍在翻页 → 任务状态保持「运行中」直到翻页队列清空才转 idle,属正常。
  • 后台翻页不带 cookie,与用户的 Google 账号解耦(更安全),实测无 cookie 也能拿到数据。
  • 若后台 fetch 在高频下被 Google 拦截(/sorry/),fetchPage 会识别并触发 onInterception 暂停, 安全网与旧版一致。可调小「后台翻页并发数」或调大「翻页请求间隔」。
  • 第 1 页仍必须真实开页获取(pb 参数由地图 JS 生成,无法离线构造);只有第 2+ 页用 fetch。

2026-05-22 v0.8.50 → v0.8.51 日志关键词列 + 翻页/实开间隔可配置

本次改动

  • 关键词:日志「地图实开 / 地图请求」的关键词列原本为空(显示 -),现在能正确显示对应关键词。
  • 翻页请求间隔:默认值 3 → 2,区间 2~5s 随机,可在设置里改。
  • 实开任务间隔:新增设置(默认 3~5s),即「上一个地图页关闭后,间隔多久打开下一个」。原为写死的 2~5s 常量,现改为可配置。

涉及文件

  • src/utils/google-map.ts:新增 getKeywordFromUrlgetSearchKeyword 增加 URL 兜底。
  • src/utils/storage-data.tsrequestDelayMin 默认 2;新增 taskGapMin:3 / taskGapMax:5
  • src/sections/settings/view/settings-view.tsx:新增「实开任务间隔上/下限」两个设置项 + yup 校验 + 重置。
  • src/sections/page/main-filters.tsxstart-batch 改传 gapMin/gapMax(来自 taskGap 设置)。
  • src/entrypoints/background/batch-controller.tsBatchSettings 去掉无用的 delayMin/delayMax,改为 gapMin/gapMaxfinalizeTab 用设置值(秒→ms)替代写死常量。
  • src/sections/page/log-view.tsx:关键词列宽 100 → 150。

遇到的问题

  • 问题:日志关键词列一直空白(-)。
  • 现象:批量抓取时,地图实开/请求两个 tab 的关键词都显示 -
  • 原因:批量任务标签页里 getSearchKeyword 只读 DOM 搜索框(#searchboxinput),时机/选择器不稳定,读不到值。
  • 解决方案:getSearchKeyword 增加兜底 —— DOM 读不到时解析 location.href/maps/search/<关键词> 段,地址栏始终带关键词,可靠。
  • pnpm build 成功,版本 0.8.51,改动文件 0 类型错误。

注意点

  • 关键词列显示的是完整搜索串(如 doctor, Sydney, Australia),列宽 150、超出截断、悬停看全。
  • taskGap 设置单位是秒,batch-controller 内部 ×1000 转 ms。
  • 两个间隔互相独立:翻页请求间隔 = 第 2 页起每页之间;实开任务间隔 = 一个地图标签页关闭→下一个打开之间。

2026-05-21 v0.8.49 → v0.8.50 修复 injected.js 拦截失效(无数据无日志)

问题

  • v0.8.49 把 injected.js 改成手动 patch XMLHttpRequest 来捕获 /search 响应 → 反而把 /search 拦截整个弄坏:拦截器收不到任何 /search,采集页拿不到第 1 页链接 → 无数据、无日志,「已完成页面」却在涨(每个标签页走「拿不到链接→结束」)。

改动

  • injected/index.ts:回退到 v0.8.48 已验证可用的 @mswjs/interceptors 拦截器(捕获 /search URL)。
  • content-button.tsx 无需改动:startBatchSearch 已有兜底 —— 捕获项无响应体时自动在本标签页内请求第 1 页。

说明

  • 2「不二次请求」的核心(实开 + 独立工作页请求 两段冗余)已由单标签页架构解决;第 1 页现在只在本标签页内取一次、记一条「实开」。

遇到的问题

  • pnpm build 成功,版本 0.8.50,0 类型错误。
  • 教训:injected.js 的 /search 拦截只用 v0.8.48 验证过的 @mswjs 方式,不要轻易换手动 patch。

2026-05-21 v0.8.48 → v0.8.49 合并采集/工作页为单标签页 + 5 项修复

问题(v0.8.48 测试反馈)

  • 5:常驻「工作页」被 Chrome 后台丢弃后不会重建 → 一直实开无请求、结果数量卡死。

  • 2:实开后又二次请求第 1 页,冗余。

  • 1 实开日志缺关键词;#3 设置页不能滚动;#4 实开条目无数量、日志想分子 tab。

改动(架构收敛)

  • 取消「采集线 + 独立工作页」双线,改为单标签页架构:一个任务一个标签页,自己开页 + 取第 1 页 + 按需翻后续页 + 关闭;不再有常驻工作页(根治 #5)。
  • injected/index.ts:改为直接 patch XMLHttpRequest,捕获 /search 的 URL 与响应体 —— 第 1 页直接用页面自身请求的响应,不再二次请求(修 #2)。
  • content-button.tsx:合并为 startBatchSearch;第 1 页(实开)与第 2 页起(请求)分别记日志、带数量与关键词。
  • batch-controller.ts:收敛为单标签页调度(开页 → 自翻页 → 关 → 下一个,可并发 K)。
  • log-view.tsx:3 子 tab(地图实开 / 地图请求 / 官网)+ 关键词列。
  • settings-view.tsx:设置页加滚动(修 #3)。

注意点

  • 第 1 页满 20 才翻第 2 页及以后;不满则止于第 1 页。翻页不滚动(构造 URL)。

遇到的问题

  • pnpm build 成功,版本 0.8.49,改动文件 0 类型错误。
  • 浏览器实测结果待补充。

2026-05-21 v0.8.47 → v0.8.48 日志界面修复(铺满高度 + 单行截断 + 复制)

问题

  • 日志列表固定 480px 高,窗口高时下方留一大片空白。
  • 网址极长导致每条换行、把行撑得很高,界面凌乱。

改动

  • log-view.tsx:列表高度改为随窗口自适应;每条日志固定单行,网址过长用省略号截断;行末加「复制链接」按钮。

遇到的问题

  • copy-to-clipboard 缺类型声明,改用 navigator.clipboard.writeText 实现复制。
  • pnpm build 成功,版本 0.8.48,0 类型错误。

2026-05-21 v0.8.46 → v0.8.47 官网抓取多线程/独立窗口 + 关页延迟 + 日志增强

本次改动(5 项)

  1. 官网/社媒抓取多线程:设置新增「官网抓取并发数」(1–10,默认 1);engine-manager.manageQueue 改为并发 K 个。
  2. 官网/社媒抓取移到独立隐藏窗口(不占用户窗口)。
  3. 采集页 / 官网页 关闭前预留 200–300ms 延迟。
  4. 日志:地图翻页条目带「页码 + 数量」,网址可点击打开对应数据链接。
  5. 日志:工作页每翻一页记一条(第 2/3/4… 页 + 数量),并标「请求获取」区别于「真实打开」。

改动文件

  • storage-data.ts / settings-view.tsx:新增 deepScrapeConcurrency 设置。
  • engine-manager.tsmanageQueue 改为并发 K;终点关闭官网窗口。
  • scraper-executor.ts:去掉单标签页串行限制;社媒日志标 opened:false。
  • dynamic-scraper.ts:官网开在独立窗口、关页前延迟 250ms。
  • scrape-window.ts:支持采集窗口 + 官网窗口两个独立窗口。
  • page-log.ts / log-view.tsx:日志条目加 page/count/opened 字段及展示(可点击打开链接)。
  • content-button.tsx / background/index.ts:工作页每翻一页上报日志(log-page)。

注意点

  • 官网并发默认 1(保持原行为);调高即多线程,速度提升但内存/风控压力上升。
  • 日志「请求」= 后台请求获取(非真实打开页面);「实开」= 真实打开了浏览器页面。

遇到的问题

  • pnpm build 成功,版本 0.8.47,改动文件 0 类型错误。
  • 顺手修掉 dynamic-scraper.ts 第 109 行的历史类型告警(response.result 类型,自 v0.8.37 起就有)。
  • 浏览器实测结果待补充。

2026-05-21 v0.8.45 → v0.8.46 采集线 / 工作页 双线(采集页关掉后继续翻页)

本次目标

  • 用户要:采集页拿到链接立即关,之后继续抓第 2 页及以后。
  • 实现「采集线 + 常驻工作页」双线:
  • 采集线:逐个开地图标签页 → 抓第 1 页链接 → 立即关页 → 等 2–5s → 下一个。
  • 工作页:一个常驻的隐藏地图标签页,从链接队列取任务,在页内翻第 1、2、3… 页(页内同源请求,已验证可靠),数据经 has-new-data 入库。
  • 两条线并行 —— 采集页关掉后,工作页继续翻该任务后边的页。

改动

  • batch-controller.ts:重写为采集线 + 工作页双线(链接队列 + 常驻工作页标签页)。
  • content-button.tsx:新增「采集模式」(只抓第 1 页链接)和「工作页翻页模式」(给定 page1Url 翻完整任务)。
  • background/index.ts:接线 batch-harvested / batch-paginate-done

注意点

  • 第 2 页起用 buildPageTwoFromInitial 构造、不滚动;构造页若无新结果,该任务止于第 1 页。
  • 工作页是一个常驻隐藏地图标签页(在采集窗口内),批量结束后关闭。
  • 翻页数据只能由页内请求取得 —— 后台直接 fetch 不行(v0.8.40-42 已验证),所以用工作页。

遇到的问题

  • pnpm build 成功,版本 0.8.46,改动文件 0 类型错误。
  • 浏览器实测结果待补充。

2026-05-21 v0.8.44 → v0.8.45 修复官网/社媒抓取被卡住(一直 0)

问题

  • 地图数据采到了(如 41 条),但官网邮箱/社媒抓取一直 0 —— 全部卡在「待抓取」。

原因

  • v0.8.42 为「错峰」给 manageQueue 加的跳过逻辑 if (isHarvestingActive()) return —— 批量采集进行中把官网抓取整个挡住;批量结束后又没有可靠触发点让它恢复,于是一直不跑。

改动

  • engine-manager.ts:移除 isHarvestingActive() 跳过 —— 官网抓取与地图采集并行(v0.8.44 采集已很轻量,不会真冲突)。
  • main-filters.tsx:批量结束时主动发 start-deep-scrape,触发官网抓取。
  • batch-controller.ts:移除不再用到的 isHarvestingActive

注意点

  • 官网/社媒抓取还需面板上「提取官网 邮箱/社媒」开关为开启状态,否则 manageQueue 会因 is_engine_running 为 false 而不跑。

遇到的问题

  • (待测试后补充)

2026-05-21 v0.8.43 → v0.8.44 采集只取第1页 + 新增日志面板

本次改动(按用户确认的方案 A)

  • 需求 1:批量采集改为「只取第 1 页」—— 采集页抓到第 1 页链接、页内取这 20 条后立即关页,不翻页、不滚动。约 10–13s/任务。
  • content-button.tsxstartBatchSearch 截断为只处理第 1 页;去掉 requestBatchSlot
  • 需求 2:主面板新增「日志」tab,记录插件打开过的页面(地图采集页 / 官网 / 社媒)。
  • 新增 utils/page-log.ts(日志存储,环形缓冲 1000 条)、sections/page/log-view.tsx(日志界面)。
  • page-main-view.tsx 加「日志」tab。
  • batch-controller.ts 开地图页时记日志;dynamic-scraper.ts 开官网时记日志;scraper-executor.ts 遇社媒链接时记日志。

注意点

  • 「只取第 1 页」每个搜索得约 20 条;要更多数据靠更细的关键词/地区组合。
  • 谷歌地图翻页数据只能由页内请求取得 —— 这是「只取第 1 页」方案的由来。
  • 插件不单独打开社媒页:日志里「社媒」记录的是"商家官网字段本身是社媒链接"的情况。

遇到的问题

  • pnpm build 成功,版本 0.8.44,改动文件除一处历史告警外 0 类型错误。
  • dynamic-scraper.ts 第 109 行 response.result 有历史类型告警 —— 非本次引入(v0.8.37 起就有),不影响构建。
  • 浏览器实测结果待补充。

2026-05-21 v0.8.42 → v0.8.43 翻页改回标签页内执行(修复"插件无结果")

问题(v0.8.42 测试反馈)

  • 页面已展示结果,但插件中没有结果。
  • 根因:v0.8.40 起翻页请求改由后台 service worker 直接 fetch 谷歌 /search。但谷歌 /search 只对「真实页面内的同源请求」正常返回数据;后台无页面上下文、跨源 fetch 拿不到可解析的数据 → 采集到了链接,但内容提取不到。
  • 这是之前一直标注「待验证」的风险点,现确认:后台直接请求不可行。

改动

  • 翻页请求改回在标签页内执行(v0.8.38 已验证可用:同源 request + has-new-data → popup 入库链路)。
  • batch-controller.ts:恢复 v0.8.39 式调度 —— 开任务标签页、页内自行翻页、上报进度/完成;一次一个标签页(并发默认 1,无预加载);任务间隔 2–5s。
  • content-button.tsx:恢复 v0.8.39 的 startBatchSearch(页内翻页)。
  • background/index.ts:恢复 batch-progress / batch-done / request-slot 接线。
  • 删除 search-worker.ts(后台 fetch 方案废弃)。
  • 采集窗口保持 v0.8.42 的 focused:false(不抢焦点);与官网抓取错峰保持。

注意点

  • 标签页需在采集窗口里停留约 20–30s 完成该任务翻页(数据只能从页面内请求取得);窗口不抢焦点、不影响用户。
  • 这是「立刻关闭标签页」与「拿得到数据」的取舍 —— 数据可靠性优先。

遇到的问题

  • (待测试后补充)

2026-05-21 v0.8.41 → v0.8.42 采集窗口不抢焦点 + 与官网抓取错峰

问题(v0.8.41 测试反馈)

  • 点 1:官网邮箱抓取(engine-manager,开标签页加载商家网站)与采集线(开谷歌地图)同时开标签页、争抢资源 → 采集偶尔抓不到链接。
  • 点 2:每次采集都把采集窗口前置(windows.update focused:true),反复抢焦点,影响用户正常操作。

改动

  • scrape-window.ts:采集窗口改为 focused:false 创建,且不再每次抓取前置 —— 不抢焦点、不再反复弹窗。
  • batch-controller.ts:新增 isHarvestingActive();采集失败自动重试一次。
  • engine-manager.tsmanageQueue 在批量采集进行中时跳过 —— 官网抓取与地图采集错峰,采集结束后由心跳闹钟自动恢复。

注意点

  • 谷歌地图必须可见才会运行:采集窗口虽不抢焦点,但不要最小化 / 不要完全遮住,否则采集会暂停(采集阶段是前期一小段,之后纯后台请求无窗口)。
  • 官网抓取在采集阶段结束后自动开始(心跳闹钟每分钟巡检)。

遇到的问题

  • (待测试后补充)

2026-05-21 v0.8.40 → v0.8.41 采集改用前台窗口

问题(v0.8.40 测试反馈)

  • 用当前窗口的 active:false 后台标签页采集 → 抓不到第 1 页链接。
  • 原因:谷歌地图是重型 SPA,标签页从未可见(never-focused 后台标签)时,地图 JS 被 Chrome 冻结/延迟渲染,不触发 /search 请求,采集失败。后台标签页天然跑不起来谷歌地图。

改动

  • 采集线改为:开一个独立的前台窗口(focused),采集标签页在其中打开(active);每个任务前都前置该窗口,确保地图真正运行、能抓到链接。
  • 采集阶段全部结束后自动关闭采集窗口。
  • 后台 fetch 请求第 2 页及以后不变。
  • scrape-window.ts:改为采集窗口管理(openHarvestTab / closeHarvestWindow)。
  • batch-controller.tsharvestOne 用采集窗口;采集完成后关窗。

注意点

  • 采集窗口需前台可见地图 SPA 才会运行 —— 这是「能抓到链接」与「不打扰」的固有权衡;采集阶段(每任务约 10s)会前置该窗口。
  • 后台翻页 fetch(无窗口)能否拿到数据仍待本轮测试验证。

遇到的问题

  • (待测试后补充)

2026-05-21 v0.8.39 → v0.8.40 采集/请求双线 + 后台直接请求

本次目标(按用户测试反馈调整架构)

  • 反馈 1:不再开独立新窗口;改为在当前窗口active:false 后台标签页(不抢焦点、不影响在用标签)。
  • 反馈 2:采集线一次只开 1 个地图标签页 —— 抓到第 1、2 页链接后立即关页 → 等 2–5s → 开下一个;请求线在后台用 fetch 直接请求第 2 页及以后,与采集线并行、互不影响。
  • 即 producer-consumer:采集线(瞬时后台标签页)+ 后台请求 worker

改动文件(计划)

  • scrape-window.ts:去掉隐藏窗口,改为当前窗口的后台标签页。
  • 新增 entrypoints/background/search-worker.ts:后台翻页 fetch + 解析 + 转发入库。
  • batch-controller.ts:重写为「采集线 + worker 池 + 链接队列」。
  • content-button.tsx:批量模式从「整轮翻页」改为「只采集第 1、2 页链接」。
  • background/index.ts:消息接线调整。

注意点

  • 后台无标签页时直接 fetch 谷歌 /search:带 cookie(credentials:'include' + host 权限)应可用;若被拒,加 declarativeNetRequest 请求头规则修正 Referer。
  • 采集线与请求线解耦:某任务失败不阻塞其它任务。
  • 采集间隔 2–5s(随机);翻页请求间隔沿用设置项;并发数默认 1(安全)。
  • 数据入库链路不变:后台 worker 仍把原始响应 has-new-data → popup 转发入库。

实现完成(构建通过)

  • scrape-window.ts:改为在当前窗口开 active:false 后台标签页 + openVerifyTab(拦截时打开可见页)。
  • 新增 search-worker.ts:后台 fetch 翻页 + 解析 + 转发入库。
  • 重写 batch-controller.ts:采集线(1 标签页、串行、间隔 2–5s)+ K 个请求 worker + 链接队列;用 runId 代号保证旧批次循环安全退出。
  • content-button.tsx:批量模式改为「只采集第 1、2 页链接」。
  • 改动文件 0 类型错误,pnpm build 成功,版本 0.8.40。

遇到的问题

  • 问题:batch-controller.ts 循环里 TS 把 status 错误收窄,报「比较无重叠」。
  • 解决:加 isIdle() 函数读取,避免收窄。
  • 待验证(浏览器实测):后台 fetch 谷歌 /search 能否带 cookie 正常拿到数据 —— 这是本架构关键点;若拿不到,需加 declarativeNetRequest 请求头规则。

注意点

  • 后台 worker 用 fetch(..., {credentials:'include'}) 直接请求,无标签页上下文。
  • 采集标签页 active:false 开在当前窗口,一次一个、抓完即关。
  • 拦截时:暂停 + 打开可见谷歌页 + 通知,用户验证后在搜索界面点「继续」。

2026-05-21 v0.8.38 → v0.8.39 批量抓取流水线 + 隐藏窗口(阶段1)

本次目标(阶段 1)

  • 批量搜索从「串行:开页 → 等翻完 → 关 → 下一个」改为「流水线 + 并发」。
  • 所有插件自动打开的地图页放进一个独立的「最小化、不聚焦」隐藏窗口,不干扰用户正常浏览器。
  • 多个任务标签页并发抓取(并发数可配)。
  • 后台全局限速:阶段 1 限速器保持「总请求频率 = 原单标签页频率」,提速来自流水线(隐藏页面开销),不增加对 Google 的请求频率,安全。
  • 拦截降级:检测到 Google 拦截(验证码 / unusual traffic / /sorry)→ 暂停 → 隐藏窗口弹出前置让用户验证 → 通过后继续。
  • 手动单次搜索(点插件放大镜)不受影响,保持 v0.8.38。

实现说明

  • 翻页请求仍在标签页内执行(复用 v0.8.38 已验证的同源请求逻辑),相比纯后台 worker 改动更小、风险更低。
  • 阶段 2(后续):放开限速器到「每标签页独立计时」,实现真正的并发倍速,按封号风险权衡。

改动文件(计划)

  • 新增 src/utils/scrape-window.ts:隐藏窗口与标签页管理。
  • entrypoints/background/:任务队列调度 + 全局限速 + 拦截处理。
  • content-button.tsx:限速取令牌、拦截检测、按 tabId 上报状态。
  • main-filters.tsx:调度改为流水线并发。
  • storage-data.ts / settings-view.tsx:新增并发数设置。

实现完成(构建通过)

  • 新增 src/utils/scrape-window.ts(隐藏窗口管理)、src/entrypoints/background/batch-controller.ts(批量调度 + 限速 + 拦截处理)。
  • 改造 background/index.ts(接入调度消息)、content-button.tsx(新增后台指令驱动的批量模式,手动模式保持 v0.8.38)、main-filters.tsx(调度委托给后台)、storage-data.ts / settings-view.tsx(新增「并发任务数」设置)。
  • 改动文件 0 类型错误,pnpm build 成功,产物 dist/chrome-mv3/,版本 0.8.39。
  • 默认并发数 = 1(阶段 1 安全值);全局限速器保持「总请求频率 = 单标签页频率」。
  • 数据入库链路不变:每页仍 has-new-data → popup 解析入库。

遇到的问题

  • (待浏览器测试后补充)

阶段 1 已知限制(阶段 2 再完善)

  • 拦截检测主要靠 /search 响应里的拦截特征;若 Google 把地图页整体换成验证码页(仍是 /maps/),会表现为「找不到搜索按钮」→ 该任务直接结束,不一定触发全局暂停。
  • 并发 = 1 时提速主要来自流水线(隐藏页面加载开销),约 25–30%;真正倍速需阶段 2 放开限速器 + 调高并发。

注意点

  • 并发数、限速强度影响封号风险,阶段 1 默认保守(并发 1)。
  • 隐藏窗口最小化后标签页仍会加载运行(Chrome 后台标签有轻微节流,不影响抓取)。
  • 手动单次搜索(地图页点插件放大镜)不受本次改动影响。

2026-05-21 v0.8.37 → v0.8.38 地图抓取改为直接请求翻页

本次改动

  • 抓取机制重构:地图列表抓取从「循环滚动触发翻页」改为「直接构造翻页请求」。
  • 第 1 页:拦截器自然捕获(搜索即产生,无需滚动)。
  • 第 2 页:先尝试直接构造(零滚动);失败则滚动一次取 Google 真实第 2 页 URL 作模板。
  • 第 3 页起:基于第 2 页模板按公式直接请求,间隔随机 3–5 秒(可配)。
  • 失败兜底:保留旧的完整滚动逻辑,新模式失败自动回退。
  • 新增 src/utils/maps-pagination.ts:/search URL 的 pb 参数解析与翻页 URL 构造。
  • src/utils/storage-data.ts:设置项新增 requestDelayMin/Max(请求间隔,默认 3–5 秒)。
  • src/sections/settings/view/settings-view.tsx:新增「翻页请求间隔」设置 UI。
  • src/sections/content-button/index.tsx:重写 startSearch,改为直接请求 + 兜底。

翻页规则(解码自 4 个真实抓包 URL)

  • 8i 偏移 = (页码-1)×20,第 1 页无此字段。
  • 12e5 = 初始搜索,12e22 = 翻页;翻页请求去掉 18e1522m622m5、加 46m1!1e10
  • 22m1s/17s 计数器是会话累积值、非线性,无法纯公式推算 → 用会话内递增值占位。
  • 第 2→N 页 pb 结构完全不变,仅 8i 与计数器变化,零结构风险。

遇到的问题(构建阶段)

  • 问题:环境未安装 pnpm 与依赖。
  • 解决:npm i -g pnpm 安装 pnpm 11,再 pnpm install
  • 问题:pnpm 11 默认忽略依赖安装脚本(esbuild、spawn-sync),pnpm installERR_PNPM_IGNORED_BUILDS 退出码 1 结束,连带 pnpm dev/build 的依赖预检失败、命令跑不起来。
  • 原因:pnpm 11 出于安全默认不跑依赖构建脚本;且 package.json 的 pnpm 字段已不再被读取。
  • 解决:新建 pnpm-workspace.yaml,写入 allowBuilds: { esbuild: true, spawn-sync: true }。之后 pnpm install/build/dev 均正常。
  • 问题:tsc --noEmitbackup/ 一起扫了,且 backup 里的旧文件经 @ 别名引用主 src,产生大量串扰报错。
  • 解决:tsconfig.json 增加 exclude: ["backup","test",".output","dist","node_modules"]
  • 问题:构建产物默认在 .output/(隐藏文件夹),macOS「加载已解压扩展」窗口里看不到、选不了。
  • 解决:wxt.config.tsoutDir: 'dist',产物改到可见的 dist/chrome-mv3/
  • 说明:项目本身有较多历史 TS 报错(autocomplete 等组件),pnpm compile 一直不通过;WXT 用 Vite/esbuild 构建、不做类型检查,不影响出包。本次仅确保改动的 4 个文件 0 类型报错,并以 pnpm build 成功为准。
  • 构建结果:pnpm build 成功,产物 dist/chrome-mv3/,manifest 版本 0.8.38。

待验证(浏览器实测)

  • 直接构造第 2 页能否成功(零滚动路径),还是回退到「滚动一次取模板」。
  • 第 3 页起翻页是否正常返回新数据,停止条件(不足一页/重复)是否生效。
  • 实测结果请补充到本节。

注意点

  • 数据入库链路不变:每页 fetch 后仍 sendMessage('has-new-data', {resData, keyword}, 'popup'),popup 用 parseSearchData 解析入库。
  • 直接构造第 2 页沿用第 1 页 token(t:11886),Google 真实第 2 页 token 不同(t:246204);若构造页返回空/全重复,自动回退「滚动一次取真实模板」。
  • Google 单会话约 120 条后降准/重复,停止条件:某页有效结果 <20 / 出现重复 googleId / 到页数上限(15)。
  • 任务标签页关闭保护改为「进度长时间不推进才关闭」,避免新流程耗时较长被误杀。
  • 测试方式:pnpm build 后在 chrome://extensions 重载扩展,打开 Google 地图搜索验证。

2026-05-21 建立更新规则

本次改动

  • 在根目录新建 更新规则.md,梳理版本更新的三条核心规则与标准流程。
  • 新建 backup/ 备份目录(含说明 README)。
  • 新建本文件 development-log.md
  • 新建 CLAUDE.md,让 AI 协助更新时自动遵守上述规则。

注意点

  • 当前版本:v0.8.37(package.json)。
  • 后续每次更新前,先读 更新规则.md 和本日志。
  • 构建输出目录为 dist/chrome-mv3/