fix(accounts): keep first login launch in one window
This commit is contained in:
@@ -92,9 +92,9 @@ T-538 后统一数据根为 `data/`:打包版默认 `<exe目录>/data`,源
|
||||
|
||||
## 四、多账号隔离方案(决策)
|
||||
|
||||
采用**每账号独立 user-data-dir**(非 Chrome profile)。`--remote-debugging-port` 绑定在 user-data-dir/进程上,profile 方案无法每账号独立 CDP、串号风险高。启动主路径用程序 `subprocess` 直启(`--remote-debugging-port` + `--remote-allow-origins=*` + `--user-data-dir`);可选生成 `.lnk` 快捷方式(PowerShell `WScript.Shell`,参数写在「目标」字段)。
|
||||
采用**每账号独立 user-data-dir**(非 Chrome profile)。`--remote-debugging-port` 绑定在 user-data-dir/进程上,profile 方案无法每账号独立 CDP、串号风险高。启动主路径用程序 `subprocess` 直启(`--remote-debugging-port` + `--remote-allow-origins=*` + `--user-data-dir`);冷启动登录入口还追加 `--no-first-run`、`--no-default-browser-check`,并把经过校验的 `https://<region_host>/portal/` 作为唯一启动 URL 放在参数末尾,避免全新 profile 的 `chrome://intro/` 另开首次运行窗口。可选生成 `.lnk` 快捷方式(PowerShell `WScript.Shell`,参数写在「目标」字段),快捷方式不携带上述冷启动专用参数和 URL,保持原行为。
|
||||
|
||||
同一账号重复点击④「启动登录」不得重复执行 `subprocess.Popen`。正确流程是先探测该账号 `debug_port` 的 `/json/version`:端口未响应才按上述启动参数新开 Chrome;端口已响应则复用该账号现有 Chrome/CDP,打开或激活卖家中心登录 tab 供人工登录,并记录为复用,不创建第二个账号窗口。
|
||||
同一账号重复点击④「启动登录」不得重复执行 `subprocess.Popen`。正确流程是先探测该账号 `debug_port` 的 `/json/version`:端口未响应才按上述启动参数新开 Chrome;CDP 就绪后在最多 2 秒的有界预算内等待初始卖家中心 page target,出现后直接激活。若只出现唯一的 `about:blank`、Chrome 新标签页或全新 profile 的 `chrome://intro/`,则导航并复用该 target;只有完全没有安全可复用 page target 时才兜底创建一次,并返回 `fallback_reason`。端口已响应时复用该账号现有 Chrome/CDP,优先激活卖家中心/登录 tab;没有时才新增一个 tab,绝不改写或关闭用户已有普通页面。④ GUI 在启动期间禁用账号选择和操作,同账号连续触发写 `result=ignored reason=launch_in_progress`,不进入第二次底层启动。
|
||||
|
||||
## 五、数据模型
|
||||
|
||||
@@ -464,7 +464,7 @@ data/images/<batch_id>/<slug>/<task_id>_<item_id>_new.<ext> # AI 生成的新
|
||||
|
||||
- 无 Shopee tab 时打开卖家中心根地址 `https://<region_host>/`(默认 `https://seller.shopee.tw/`);不自动登录。重定向到登录页返回明确 `LOGIN_PAGE`;页面 target 可用且 Cookie API 至少成功一次、但确实缺少 `SPC_ST`/`SPC_U` 时返回 `NO_SESSION_COOKIE`;websocket/target 正在关闭、整个检测周期一次 Cookie 都未成功读取时返回 `LOGIN_CHECK_TARGET_UNAVAILABLE`,界面显示“登录状态暂不可确认”,不得误报账号退出登录。
|
||||
- 多个 Shopee page target 并存时优先稳定的卖家中心 portal 页面,再尝试商品页,显式登录页最后判定;单个 target 连接或 Cookie 读取失败后立即重枚举/改连其他未尝试 target,不等待完整 8 秒才交给外层重试。①采集的 retry/recovered 日志必须带当前任务 ID、商品 ID;关闭上一条商品页的 target 仍短暂出现在 `/json` 时,不得把上一条 URL 误记为下一条账号掉线。
|
||||
- ④「启动登录」只负责准备该账号独立 user-data-dir + CDP 端口的 Chrome,供用户人工登录;该入口必须幂等:若端口已响应,复用现有账号 Chrome 并打开/激活卖家中心登录 tab,不再新开 Chrome;若端口未响应,才启动 Chrome。「检测登录」只验证当前 Chrome/CDP/会话 Cookie 是否可用。① 采集的预检会复用同一幂等启动能力,自动确保本轮匹配账号 Chrome 就绪但不自动登录;③ 更新的预检只检测,不自动启动缺失浏览器。若商品详情页或卖家中心重定向到 `accounts.shopee.tw/seller/login`,必须按登录页处理,返回 `LOGIN_PAGE` 并在 GUI 显示未登录。
|
||||
- ④「启动登录」只负责准备该账号独立 user-data-dir + CDP 端口的 Chrome,供用户人工登录;该入口必须幂等:若端口已响应,复用现有账号 Chrome 并打开/激活卖家中心登录 tab,不再新开 Chrome;若端口未响应,才用卖家中心初始 URL 启动 Chrome,并优先复用本轮初始 page target,避免空白窗口后再建第二页。返回结果用 `created_tab/startup_target_reused/startup_page_navigated/page_target_count/fallback_reason` 说明实际路径,`chrome_launch` 日志同步记录且不得包含密码、Cookie 或 token。「检测登录」只验证当前 Chrome/CDP/会话 Cookie 是否可用。① 采集的预检会复用同一幂等启动能力,自动确保本轮匹配账号 Chrome 就绪但不自动登录;③ 更新的预检只检测,不自动启动缺失浏览器。若商品详情页或卖家中心重定向到 `accounts.shopee.tw/seller/login`,必须按登录页处理,返回 `LOGIN_PAGE` 并在 GUI 显示未登录。
|
||||
- T-585 后新配置的 `chrome_path` 默认留空。程序在数据目录就绪、强制升级检查通过后、创建主窗口前,仅当当前路径为空或不可启动时,按当前用户/本机 Windows App Paths(含 64/32 位视图)、标准 Chrome 目录和 `PATH` 自动寻找 `chrome.exe`;命中才持久化归一化绝对路径,并在状态栏显示“已自动定位 Chrome”。有效的自定义/便携版路径和可从 PATH 启动的 `chrome.exe` 不覆盖;不扫描整盘、不检测 Edge 或 Chromium。⑤的“自动检测”只填入输入框并标记未保存,仍由用户点“保存设置”确认写入。
|
||||
|
||||
## 七、CDP 已验证事实(务必遵守)
|
||||
|
||||
+5
-5
@@ -222,7 +222,7 @@ login_status_text(status) -> str
|
||||
- `create_account()` / `update_account()` 负责生成 slug、创建 `chrome_user_data_dir/<slug>` 并写 DB;编辑别名会生成新 slug/目录,但不删除旧 user-data-dir。
|
||||
- `debug_port` 在账号服务层按账号唯一校验;默认端口取 `debug_port_range` 中第一个未占用端口。
|
||||
- `delete_account()` 只删除 DB 账号记录,不删除本地 user-data-dir,避免误删登录态。
|
||||
- `launch_for_login()` 是幂等入口。先检查 `chrome.is_running(account.debug_port)`;若该账号 CDP 端口已响应,不再调用 `subprocess.Popen`,而是复用已打开的账号 Chrome,优先激活/打开 `https://<region_host>/portal/` 或卖家中心登录 tab,并返回 `reused=true`;若端口未响应,才启动带该账号 user-data-dir 和 CDP 端口的 Chrome,等待 CDP 就绪并返回 `launched=true`。不会读取、填写或提交密码,不绕过验证码。
|
||||
- `launch_for_login()` 是幂等入口。先检查 `chrome.is_running(account.debug_port)`;若该账号 CDP 端口已响应,不再调用 `subprocess.Popen`,而是复用已打开的账号 Chrome,优先激活/打开 `https://<region_host>/portal/` 或卖家中心登录 tab,并返回 `reused=true`,且不会改写已有普通页面。若端口未响应,才启动带该账号 user-data-dir、CDP 端口和唯一卖家中心初始 URL 的 Chrome;CDP 就绪后短时等待并复用初始 target,只有无安全可复用 page target 时才兜底创建一次。返回值除 `action/pid/target_id/url/created_tab` 外,还带 `initial_url/startup_target_reused/startup_page_navigated/page_target_count/fallback_reason/target_probe_error` 供日志诊断。不会读取、填写或提交密码,不绕过验证码。
|
||||
- ③ 更新蝦皮的账号预检不会自动调用 `launch_for_login()`;Chrome 未启动/端口不可达时只返回阻断原因,由 GUI 提示用户去④手动打开账号浏览器并登录。T-105b 的复用逻辑只作用于④用户主动点击「启动登录」这一入口。
|
||||
- `create_shortcut()` 生成 `.lnk`,目标/参数复用 `chrome.build_launch_args()`,不包含密码。
|
||||
- `detect_login()` 复用 `editor.login_status()`;检测为已登录时更新 `last_login_at`。
|
||||
@@ -231,15 +231,15 @@ login_status_text(status) -> str
|
||||
|
||||
```python
|
||||
class ChromeLaunchError(RuntimeError): ...
|
||||
build_launch_args(account, config=None) -> list[str]
|
||||
build_launch_args(account, config=None, initial_url=None) -> list[str]
|
||||
# chrome + --remote-debugging-port + --remote-allow-origins=* + --user-data-dir
|
||||
launch_chrome(account, config=None) -> subprocess.Popen
|
||||
launch_chrome(account, config=None, initial_url=None) -> subprocess.Popen
|
||||
create_shortcut(account, shortcut_path=None, desktop_dir=None, name=None, config=None) -> str
|
||||
wait_debug_ready(port, timeout=60, host="127.0.0.1") -> bool
|
||||
is_running(port, host="127.0.0.1") -> bool
|
||||
```
|
||||
|
||||
`build_launch_args()` 接受 dict 或对象形式账号;账号需有 `debug_port`,并有 `user_data_dir` 或 `slug/alias`。端口探测访问 `/json/version`,显式禁用环境代理。`create_shortcut()` 使用 PowerShell `WScript.Shell.CreateShortcut` 生成 `.lnk`,`TargetPath` 为 Chrome,`Arguments` 含 `--remote-debugging-port`、`--remote-allow-origins=*`、`--user-data-dir=<该账号目录>`。
|
||||
`build_launch_args()` 接受 dict 或对象形式账号;账号需有 `debug_port`,并有 `user_data_dir` 或 `slug/alias`。可选 `initial_url` 仅接受不含账号密码的蝦皮 `http/https` 地址;传入时追加 `--no-first-run`、`--no-default-browser-check`,并把该 URL 作为唯一 URL 参数放在末尾,避免全新 profile 的首次运行页占用独立窗口;不传时参数保持兼容。端口探测访问 `/json/version`,显式禁用环境代理。`create_shortcut()` 使用 PowerShell `WScript.Shell.CreateShortcut` 生成 `.lnk`,`TargetPath` 为 Chrome,`Arguments` 含 `--remote-debugging-port`、`--remote-allow-origins=*`、`--user-data-dir=<该账号目录>`,不自动追加上述冷启动专用参数或卖家中心 URL。
|
||||
|
||||
## cdp 模块(`app/cdp.py`,T-000 由根目录 `cdp.py` 迁入)
|
||||
|
||||
@@ -460,7 +460,7 @@ T-523 后 GUI 已从旧 `app/gui.py` 拆为 `app/gui/` 包:`__init__.py` 负
|
||||
|
||||
- 表格列:账号名、别名、地区、端口、登录状态、备注;不展示密码。
|
||||
- 弹窗字段:账号名、别名、地区、调试端口、密码、备注、slug、数据目录;密码框使用打码显示;首次保存/变更非空密码前弹窗提示“本地明文保存”。
|
||||
- 「启动登录」必须幂等:若该账号 Chrome/CDP 已打开,则复用现有窗口并打开/激活卖家中心登录 tab,不重复启动 Chrome;未打开时才新启动 Chrome,仍由用户人工登录。「检测登录」用 worker 跑 `accounts.detect_login()` 并刷新状态列;若当前 URL 跳到 `accounts.shopee.tw/seller/login`,状态必须显示未登录;「快捷方式」调用 `accounts.create_shortcut()` 生成默认桌面 `.lnk`。
|
||||
- 「启动登录」必须幂等:新增账号后不自动启动;若该账号 Chrome/CDP 已打开,则复用现有窗口并打开/激活卖家中心登录 tab,不重复启动 Chrome,也不覆盖普通页面;未打开时用卖家中心初始 URL 新启动并复用初始 page target,异常时最多兜底新建一个 tab。启动期间禁用账号选择及增删改/登录相关操作,连续触发只记 `ignored` 日志;成功或失败均恢复控件。`chrome_launch` 日志记录初始 target 是否复用、是否兜底建 tab 和原因。「检测登录」用 worker 跑 `accounts.detect_login()` 并刷新状态列;若当前 URL 跳到 `accounts.shopee.tw/seller/login`,状态必须显示未登录;「快捷方式」调用 `accounts.create_shortcut()` 生成默认桌面 `.lnk`。
|
||||
|
||||
⑤ 设置当前要点(T-501):
|
||||
|
||||
|
||||
+3
-3
@@ -13,7 +13,7 @@
|
||||
| ① 导入采集 | 导入多个 Excel;任务列表;**采集**商品当前的旧标题/旧封面(只读),封面图下载本地;回写 Excel 旧字段 | 只读,低 |
|
||||
| ② AI生成 | 左侧标题/封面**提示词**;右侧按批次/店铺/商品ID/状态筛选任务列表;AI 生成新标题,并按本轮开关可选生成新封面;表格拆分显示「标题状态 / 图片状态」;已生成任务可本地微调新标题;双击看新旧封面 | 不触线上,中 |
|
||||
| ③ 更新蝦皮 | 对**已生成**任务点击「开始更新」后弹窗确认;确认后打开编辑页换标题+封面并逐条点「更新」提交;结果回写 Excel | **写线上,高** |
|
||||
| ④ 账号管理 | Shopee 账号(账号名/别名/数据目录/端口/密码本地明文仅参考/登录状态);启动登录、检测登录、生成快捷方式;启动登录必须复用已打开的同账号 Chrome,避免重复开窗口;检测登录遇到 `accounts.shopee.tw/seller/login` 必须显示未登录 | 中 |
|
||||
| ④ 账号管理 | Shopee 账号(账号名/别名/数据目录/端口/密码本地明文仅参考/登录状态);启动登录、检测登录、生成快捷方式;新增账号不自动启动 Chrome,首次启动复用初始卖家中心页,重复操作复用已打开的同账号 Chrome,避免重复开窗口;检测登录遇到 `accounts.shopee.tw/seller/login` 必须显示未登录 | 中 |
|
||||
| ⑤ 设置 | cmhub 网关/API Key、生文/生图别名、托管档位提示、生成参数、Chrome 路径、默认端口、蝦皮更新执行参数等 | — |
|
||||
| ⑥ 商品套图 | 按账号+商品ID管理本地图片项目;拉取/添加商品原图,按套图分类异步生图,查看历史与重试 | 本地生成,中 |
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
- ① 导入采集 与 ③ 更新蝦皮 都依赖**账号已配置且已登录**(在 ④ 账号管理)。
|
||||
- ① 点击「采集旧标题/旧封面」后,会为本轮匹配到账号的店铺自动确保 Chrome 就绪:已打开则复用,未打开才启动;随后逐账号检测蝦皮登录态。明确进入登录页的账号任务整组略过并在结束汇总中提示去④人工登录;`NO_SESSION_COOKIE` 或 CDP 短暂读取异常只视为登录状态暂不确定,重试后仍不确定也继续尝试采集,避免误判批量略过。
|
||||
- ③ 点击「开始更新」后必须检查当前筛选结果涉及的账号;只要有账号 Chrome 未启动、CDP 端口不可访问或 Shopee 未登录,就弹窗列出账号并中止本轮更新,不创建真实更新 worker,不提交任何商品。
|
||||
- 可以提供「打开账号管理」或「启动登录」入口辅助用户处理当前账号;③ 不要无提示批量启动所有账号 Chrome,避免在提交线上前开错账号或启动过多浏览器进程。用户主动点击④「启动登录」时也必须先检查该账号 CDP 端口,已打开则复用现有 Chrome 并打开/激活卖家中心 tab,不重复 `Popen` 新窗口。
|
||||
- 可以提供「打开账号管理」或「启动登录」入口辅助用户处理当前账号;③ 不要无提示批量启动所有账号 Chrome,避免在提交线上前开错账号或启动过多浏览器进程。用户主动点击④「启动登录」时必须先检查该账号 CDP 端口:已打开则复用现有 Chrome 并打开/激活卖家中心 tab,不重复 `Popen`;未打开则直接携带卖家中心 URL 冷启动并复用初始 page target,不先开空白页再额外创建页面。启动过程中账号列表和相关按钮禁用,连续点击不排队启动第二轮。
|
||||
- 老用户账号已就绪则无感。
|
||||
|
||||
## ① 导入采集
|
||||
@@ -234,7 +234,7 @@
|
||||
| `CollectTab(QWidget)` | ① | 导入、任务表、采集、回写 |
|
||||
| `GenerateTab(QWidget)` | ② | 左提示词管理 + 右筛选/任务列表;双击看新旧封面;开始生成/停止/进度;本轮「生成内容」下拉接入 `GenerateWorker` |
|
||||
| `ApplyTab(QWidget)` | ③ | 已生成任务筛选 +「更新内容」下拉 + 缺失内容阻断 +「检查本轮更新」+ 分批开始更新确认 + 检查/真实更新运行日志 + 结果回写与结束汇总 |
|
||||
| `AccountsTab(QWidget)` | ④ | 账号增删改、启动登录、检测登录、生成快捷方式;登录检测把 Shopee accounts 登录页判为未登录 |
|
||||
| `AccountsTab(QWidget)` | ④ | 账号增删改、启动登录、检测登录、生成快捷方式;首次启动复用初始卖家中心页,启动中防重复触发,登录检测把 Shopee accounts 登录页判为未登录 |
|
||||
| `SettingsTab(QWidget)` | ⑤ | cmhub 网关配置 + 响应式三列设置表单 + 生成参数 + Chrome/端口配置 + 蝦皮更新执行;数据路径字段隐藏但保留配置兼容 |
|
||||
| `ProductSuiteTab(QWidget)` | ⑥ | 商品套图多任务、账号+商品ID上下文、原图导入/排序、套图分类、AI帮写、cmhub 异步生成、结果历史与删除撤销 |
|
||||
| `TaskTableModel(QAbstractTableModel)` | ①②③ | 任务表格数据模型,供 `QTableView` 使用 |
|
||||
|
||||
+13
-2
@@ -3,7 +3,7 @@ id: T-633
|
||||
title: ④新账号首次启动登录只打开一个 Chrome 窗口
|
||||
phase: 1
|
||||
deps: [T-105b]
|
||||
status: TODO
|
||||
status: DONE
|
||||
created: 2026-07-14
|
||||
---
|
||||
|
||||
@@ -20,6 +20,7 @@ created: 2026-07-14
|
||||
- `chrome.wait_debug_ready()` 等待 CDP;
|
||||
- `_open_or_activate_login_tab()` 再查找蝦皮页面,未找到时调用 `cdp.create_tab_info(portal_url)`。
|
||||
3. `chrome.build_launch_args()` 当前只传 Chrome 路径、调试端口、`remote-allow-origins` 和账号 `user-data-dir`,没有携带 `https://<region_host>/portal/`。因此新 Chrome 会先按自身启动策略创建空白/新标签页;CDP 就绪后代码又执行一次 `Target.createTarget` 打开卖家中心。部分 Chrome 版本或窗口状态下,这会表现为一个初始窗口加一个卖家中心窗口,而不是同一窗口内唯一页面。
|
||||
- Windows 全新临时 profile 实测进一步确认:Chrome 会先创建独立的 `chrome://intro/` 首次运行窗口并忽略命令行 URL;旧判断不把该页视为安全启动页,随后兜底 `Target.createTarget`,最终稳定复现 2 个 page target 和 2 个 `Chrome_WidgetWin_1` 顶层窗口。
|
||||
4. 现有 `tests/test_accounts.py` 的冷启动测试明确断言 `launch_chrome()` 后还会调用一次 `create_tab_info()`,说明当前自动回归把“双阶段建页”当成了正常行为,未覆盖“首次启动只产生一个可见窗口/页面”的产品要求。
|
||||
5. 本地 `chrome_launch` 运行日志中,最近两次启动记录相隔约 25 秒,各自只有一次 `start -> launched`,并记录不同 PID。该证据不支持“单次 GUI 回调调用两次 `Popen`”,但说明还需要防止用户连续点击或首轮 CDP 消失后再次启动。任务必须同时区分:
|
||||
- 一次启动进程内额外创建页面/窗口;
|
||||
@@ -32,6 +33,7 @@ T-105b 已解决“同账号 Chrome 的 CDP 端口仍在运行时,重复点击
|
||||
### 1. 冷启动直接携带卖家中心 URL
|
||||
|
||||
- 给 `chrome.build_launch_args()` / `chrome.launch_chrome()` 增加可选 `initial_url` 参数;不传时保持现有调用兼容,传入时把规范化 URL 作为唯一启动页面追加到 Chrome 参数末尾。
|
||||
- 传入 `initial_url` 的冷启动登录路径同时追加 `--no-first-run` 和 `--no-default-browser-check`,避免全新 profile 的 `chrome://intro/`/默认浏览器提示抢占独立窗口;不传 `initial_url` 的快捷方式和其他入口不追加这些参数。
|
||||
- `accounts.launch_for_login()` 在确认账号端口未运行后,计算 `https://<region_host>/portal/`,调用:
|
||||
|
||||
```python
|
||||
@@ -47,7 +49,7 @@ chrome.launch_chrome(account, config=config, initial_url=portal_url)
|
||||
- `wait_debug_ready()` 成功后,不立即把“当前没有已完成导航的蝦皮 URL”解释为必须新建 target。
|
||||
- 对本轮刚启动的 Chrome,在一个短且有上限的预算内重新枚举 `/json`,等待命令行携带的初始卖家中心页面出现;建议总预算不超过 2~3 秒、短间隔轮询,不使用无条件固定长 `sleep`。
|
||||
- 如果已经出现卖家中心或 `accounts.shopee.<区域>/seller/login` 页面,直接激活该 target,返回 `created_tab=false` / `startup_target_reused=true`,不得再调用 `Target.createTarget`。
|
||||
- 如果初始 URL 尚未完成,但本轮新 Chrome 已有唯一的普通 page target(如 `about:blank` / `chrome://newtab`),优先通过该 target 导航到卖家中心并激活,避免另建窗口。该行为只适用于“本轮刚启动”的冷启动路径。
|
||||
- 如果初始 URL 尚未完成,但本轮新 Chrome 已有唯一的普通启动 page target(如 `about:blank` / `chrome://newtab` / `chrome://intro/`),优先通过该 target 导航到卖家中心并激活,避免另建窗口。该行为只适用于“本轮刚启动”的冷启动路径;端口启动前已经运行的 Chrome 不得把 `chrome://intro/` 当作可覆盖页面。
|
||||
- 只有在有界等待结束后仍没有任何可复用的 page target 时,才允许兜底创建一个卖家中心 target;返回值和运行日志必须标记 `created_tab=true` 与兜底原因。
|
||||
- 对“端口启动前已经运行”的 Chrome 继续沿用 T-105b:优先激活现有卖家中心/登录页;若没有,新增一个卖家中心 tab。不得为了单窗口目标导航、覆盖或关闭用户已有的普通页面。
|
||||
|
||||
@@ -129,3 +131,12 @@ chrome.launch_chrome(account, config=config, initial_url=portal_url)
|
||||
- 不修改 Shopee 商品详情页 CDP 选择器、采集、标题/封面更新、AI/cmhub、Excel 或自动升级流程。
|
||||
- 不自动登录、不填写或提交密码、不读取 Cookie 值、不绕过验证码、风控或权限校验。
|
||||
- 实现时同步更新 `docs/04-architecture.md`、`docs/api.md` 和必要的 `docs/routes.md`;不修改冻结的 `docs/06-tasks.md`。
|
||||
|
||||
## 执行记录
|
||||
|
||||
- 2026-07-14 完成。`chrome.build_launch_args()` / `launch_chrome()` 已支持经过校验的蝦皮 `initial_url`;冷启动登录同时使用 `--no-first-run`、`--no-default-browser-check`,卖家中心 URL 保持为唯一末尾 URL。未传 `initial_url` 的快捷方式和既有启动调用参数不变。
|
||||
- `accounts.launch_for_login()` 已区分冷启动与已运行 Chrome:冷启动在 2 秒有界预算内复用初始卖家中心/登录 target,唯一 `about:blank`、新标签页或 `chrome://intro/` 可导航复用,完全无安全 target 时才创建一次并返回兜底原因;已运行 Chrome 不改写或关闭用户普通页面。
|
||||
- ④账号管理已增加启动中状态和连续点击保护;启动期间禁用账号列表及增删改/登录操作,底层调用成功或失败后恢复控件。同账号启动中或系统队列紧接着投递的重复点击不会再次调用 `launch_for_login()`,并写 `result=ignored reason=launch_in_progress`。启动日志新增 `created_tab/startup_target_reused/startup_page_navigated/page_target_count/fallback_reason`,且继续统一脱敏。
|
||||
- 已同步 `docs/04-architecture.md`、`docs/api.md`、`docs/routes.md`;测试覆盖启动 URL/首次运行参数校验、初始 target 立即或延迟出现、空白/intro 复用、无 target 单次兜底、运行中普通页保护、新增账号不自动启动、GUI 重入及成功/失败控件恢复。
|
||||
- Windows 全新临时 profile 初次探测复现了 `chrome://intro/` 导致 2 个 page target/2 个顶层窗口,补齐首次运行参数和 intro 复用后复测通过:首次启动为 `launched`、`created_tab=false`、1 个 page target、1 个 `Chrome_WidgetWin_1`;再次调用为 `reused` 且 target 不变;关闭后使用同一 profile 再次冷启动仍为 1 个页面、1 个窗口。验证未读取或填写凭据,临时 Chrome 已通过 CDP 关闭并清理。
|
||||
- 最终干净验证工作树中 `py -3.10 -m unittest discover -s tests` 共 495 项全部通过;`python -m ruff check app tests main.py`、`py -3.10 -m compileall app main.py`、`git diff --check` 全部通过。工作区中用户未提交的提示词、版本号、历史任务归档和 HTML 样本未纳入验证快照或提交。
|
||||
|
||||
Reference in New Issue
Block a user