Files
cmshoppe/docs/tasks/T-578.md
T

91 lines
7.4 KiB
Markdown
Raw Normal View History

---
id: T-578
title: ③更新失败时关闭本次新开的商品编辑页(app 建的 tab),只保留成功页由⑤开关决定
phase: 7
2026-07-09 21:04:47 +08:00
deps: [T-402, T-404b, T-501c, T-571]
2026-07-09 21:08:42 +08:00
status: DONE
created: 2026-07-09
---
## 问题 / 背景
③更新蝦皮时,`apply_task`(`app/editor.py:1414`)在对应账号 Chrome 里为商品新开编辑页;当拖图到第一位失败(`DRAG_NOT_FIRST`)、上传超时等**失败**时,页面不会自动关闭。
根因(已核):`finally` 里 `_close_applied_product(cdp, close_success_tab=close_success_tab and committed)`(`editor.py:1512`)。关闭 tab 需同时满足 `close_success_tab`(⑤设置「成功后关闭本次新开编辑页」,默认 False)**且** `committed`(点了「更新」才为 True)。失败时 `committed=False`,条件必然不成立 → `cdp.close()` 只断 WebSocket、tab 原样留着。这是「失败保全现场」的原设计。
2026-07-09 21:04:47 +08:00
用户决定:**失败时关闭本次由程序自动新建的商品编辑页**,理由——失败原因/上传状态已进 run_logs 与诊断日志(`_notify_apply_step` 失败详情、run 事件),关掉页面不丢诊断数据;而失败页上的改动(删了旧封面、传了新图但未排首位)都是**未提交**表单状态,关闭 = Shopee 编辑器丢弃这些草稿,**线上商品不受影响**(未点「更新」即未持久化),重试会重新开页从头跑 `replace_cover`。累积的失败 tab(重试还会复用、进而连成功后也关不掉)问题一并消除。
2026-07-09 21:04:47 +08:00
保留的边界:**只关 `created_by_app=True` 的 tab**;若复用用户已经打开的商品编辑页,只断开 CDP 连接,不关闭浏览器 tab。
## 方案(改哪个文件、改成什么)
### `app/editor.py` — `apply_task` finally + `_close_applied_product`
统一口径:**app 新开的 tab 在「失败」或「成功且⑤开关开」时关闭;复用的 tab 永不关。** 成功页默认保留(供人工复核,⑤开关控制),失败页直接关。
2026-07-09 21:04:47 +08:00
- 改 `finally` 的传参与 `_close_applied_product`,不要继续把 `close_success_tab and committed` 预先折叠成布尔值,避免失败状态在调用处丢失。建议签名与调用改为:
- `finally: _close_applied_product(cdp, committed=committed, close_success_tab=close_success_tab)`
- `def _close_applied_product(cdp, committed=False, close_success_tab=False): ...`
- `_close_applied_product` 内部关闭判定为:
- `created_by_app and target_id and ((not committed) or close_success_tab)`。
- 即:`committed=False`(含 `replace_cover` 失败、`change_title` 失败、`click_update` 未点成、抛异常各分支)→ 关;`committed=True` 且 `close_success_tab` → 关;`committed=True` 且开关关 → 保留(不变)。
2026-07-09 21:04:47 +08:00
- **关闭前的 `time.sleep(2)` 只用于成功且 `close_success_tab=True` 的路径**(让「更新成功」状态渲染后再关,是人工复核缓冲);失败关闭不需要该延时,避免每条失败多等 2 秒拖慢批量。
- 复用现有 `close_tab`(`app/cdp.py`),关闭异常继续 try/except 吞掉(沿用现状,关不掉不致命)。
- 早期打开就失败仍走 `_close_open_product_failure`(`editor.py:745`,本就关 app tab),与本改动口径一致,不动。
### 影响面确认(不新增 worker/配置)
- 调用方 `ApplyWorker`(`workers.py:939`)传参不变(`close_success_tab` 仍来自⑤设置,只影响成功路径);**不新增设置项**——失败关闭是无条件行为(受 `created_by_app` 守卫),符合「失败了直接关闭」。
- ⑤「成功后关闭本次新开编辑页」文案/语义不变(它本就只管成功页)。
### 文档同步
- `docs/04-architecture.md` 第七节 CDP 已验证事实里「③更新失败保留页面」的表述,更新为「③更新失败关闭 app 新开页(复用页不关)、成功页由⑤开关决定」。
2026-07-09 21:04:47 +08:00
- `docs/api.md` 里 `apply_task()` / ③更新流程关于“失败任务保留现场”的接口说明同步改为同一口径,避免 API 文档与实现冲突。
## 验收要点
2026-07-09 21:04:47 +08:00
- `replace_cover` 返回 `ok=False`(如 `DRAG_NOT_FIRST`/`UPLOAD_TIMEOUT`)且 `created_by_app=True` → `apply_task` 结束后 `close_tab` 被调用,且不调用 `time.sleep(2)`。
- `replace_cover` 返回 `ok=False` 且 `created_by_app=False` → 只 `cdp.close()` 断开连接,不调用 `close_tab`。
- `change_title` 失败、`click_update` 未点成、`apply_task` 抛异常各分支:`created_by_app=True` 时关闭 app 新开 tab,`created_by_app=False` 时不关闭浏览器 tab。
- 成功且 `close_success_tab=False`(默认)→ tab **保留**,不调用 `time.sleep(2)`(既有行为不回归)。
- 成功且 `close_success_tab=True` → 先 `time.sleep(2)`,再关闭 app 新开 tab。
- 复用的既有 tab(`created_by_app=False`)→ 失败/成功均不调用 `close_tab`。
- `open_product()` 内部打开/就绪失败仍由 `_close_open_product_failure` 负责清理本轮自动新建 tab;本任务不重复改这条早期失败路径。
- 失败原因/上传状态仍出现在 run_logs / 诊断日志(关闭不吞诊断)。
- 验证命令(unittest,不引入 pytest):
- `py -3.10 -m unittest tests.test_editor_login tests.test_gui`
- `python -m ruff check app tests main.py`
- `py -3.10 -m compileall app main.py`
- `py -3.10 -m unittest discover -s tests`
- `git diff --check`
## 边界(不改什么)
- 不关闭复用的用户自有页面(`created_by_app=False`)。
- 不改 ①采集关闭逻辑(`_close_collected_product`)、④登录页。
- 不新增⑤设置项;不改 `close_success_tab` 对成功路径的语义。
- 不改 `replace_cover`/`change_title`/`click_update` 交互本身、CDP 选择器、DB、AI/cmhub。
- 不改「失败不写回蝦皮」的既有安全事实(失败页本就未提交)。
## 执行记录
2026-07-09 21:08:42 +08:00
- 2026-07-09:已完成。
- 文档预提交:
- 先按评审建议更新任务定义并单独提交 `7c606e8 T-578 更新任务定义`:补依赖、明确只关闭程序自动新建页、实现时传完整 `committed`、同步 `docs/api.md`、细化验收分支。
- 代码:
- `app/editor.py`:`apply_task()` finally 改为 `_close_applied_product(cdp, committed=committed, close_success_tab=close_success_tab)`;`_close_applied_product()` 内部统一判断 tab 生命周期。
- 更新失败(`committed=False`,含标题失败、封面失败、更新按钮/确认失败、异常分支)且 `created_by_app=True` 时关闭浏览器 target;复用用户已有 tab 时只断开 CDP。
- 成功路径保持原语义:`close_success_tab=False` 时保留;`close_success_tab=True` 且 app 新建页时先等 2 秒再关闭。失败关闭不等待 2 秒。
- `tests/test_editor_login.py`:补/改成功默认保留、失败关闭、复用失败不关、封面失败关闭、异常关闭等单测。
- 文档:
- `docs/04-architecture.md`:更新 `close_success_tab`、③真实更新、CDP tab 生命周期表述。
- `docs/api.md`:同步 `apply_task()` 和 ③更新流程接口说明,移除“失败保留现场”的旧口径。
- 验证:
- `py -3.10 -m unittest tests.test_editor_login`:通过,45 tests。
- `py -3.10 -m unittest tests.test_editor_login tests.test_gui`:通过,184 tests。
- `python -m ruff check app tests main.py`:通过。
- `py -3.10 -m compileall app main.py`:通过。
- `py -3.10 -m unittest discover -s tests`:通过,316 tests。
- `git diff --check`:通过,无输出。