From 84ec0ed1f05e029bb321120b5eca75a7636052d5 Mon Sep 17 00:00:00 2001 From: chengma Date: Fri, 14 Aug 2026 10:26:45 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=A8=B3=E5=AE=9A=E9=87=87=E8=B4=AD?= =?UTF-8?q?=E5=9C=B0=E5=9D=80=E9=A1=B5=E9=9D=A2=E5=88=87=E6=8D=A2=20(#221)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/pdd_u2_purchase_adapter.py | 16 ++++++++++++++++ client/test/test_pdd_u2_purchase_adapter.py | 20 ++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/client/src/pdd_u2_purchase_adapter.py b/client/src/pdd_u2_purchase_adapter.py index 7ea49b3..7d19296 100644 --- a/client/src/pdd_u2_purchase_adapter.py +++ b/client/src/pdd_u2_purchase_adapter.py @@ -69,6 +69,7 @@ _RISK_MARKERS = ("操作频繁", "异常请求", "风险提示", "账号异常") _PAYMENT_MARKERS = ("输入支付密码", "立即支付", "支付成功", "支付失败") _FINAL_SUBMIT_MARKERS = ("提交订单", "现在买,仅", "确认购买") _OUT_OF_STOCK_MARKERS = ("已售罄", "暂时缺货", "库存不足", "该商品已售罄") +_ADDRESS_ACTION_SETTLE_SECONDS = 1.0 _SUPPORTED_OPTION_KEYS = frozenset({"color", "size"}) _MAX_QUANTITY_BUTTON_CLICKS = 5 _KEYBOARD_STATUS_MARKERS = ( @@ -1378,6 +1379,7 @@ class U2PddLivePurchaseAdapter(U2PddPurchaseAdapter, PddLivePurchaseAdapter): "PURCHASE_ADDRESS_ENTRY_AMBIGUOUS", "规格面板没有唯一可靠的收货地址入口", ) + self._settle_after_address_action() panel_root = self._wait_for_address_page("panel") edit_root = self._open_address_edit_page(panel_root) @@ -1410,12 +1412,14 @@ class U2PddLivePurchaseAdapter(U2PddPurchaseAdapter, PddLivePurchaseAdapter): step="purchase_update_shipping_address", ) editor.set_text(new_address) + self._settle_after_address_action() save_target = self._wait_for_stable_address_save(new_address) self._click_unique_address_target( [save_target], "PURCHASE_ADDRESS_SAVE_AMBIGUOUS", "修改页没有唯一可靠的保存按钮", ) + self._settle_after_address_action() saved_root, saved_page = self._wait_after_address_save(new_address) if saved_page == "confirmation": @@ -1426,6 +1430,7 @@ class U2PddLivePurchaseAdapter(U2PddPurchaseAdapter, PddLivePurchaseAdapter): "PURCHASE_ADDRESS_BACK_AMBIGUOUS", "收货地址页没有唯一可靠的返回按钮", ) + self._settle_after_address_action() self._wait_for_address_page("confirmation") except PddPurchaseError: raise @@ -1451,6 +1456,11 @@ class U2PddLivePurchaseAdapter(U2PddPurchaseAdapter, PddLivePurchaseAdapter): (left + right) // 2, (top + bottom) // 2 ) + def _settle_after_address_action(self) -> None: + """关键地址操作后留出固定时间,再继续按页面状态确认。""" + + self._sleep(_ADDRESS_ACTION_SETTLE_SECONDS) + def _open_address_edit_page(self, panel_root: ET.Element) -> ET.Element: """稳定识别“修改”按钮;首次点击丢失时最多安全重试一次。""" @@ -1501,6 +1511,9 @@ class U2PddLivePurchaseAdapter(U2PddPurchaseAdapter, PddLivePurchaseAdapter): "PURCHASE_ADDRESS_EDIT_AMBIGUOUS", "收货地址页没有唯一可靠的修改按钮", ) + self._settle_after_address_action() + # 固定稳定等待不能占用原页面切换超时预算。 + deadline += _ADDRESS_ACTION_SETTLE_SECONDS click_attempts += 1 if first_clicked_target is None: first_clicked_target = current_target @@ -1693,6 +1706,9 @@ class U2PddLivePurchaseAdapter(U2PddPurchaseAdapter, PddLivePurchaseAdapter): if overlay_stable_reads >= 3 and system_back_attempts == 0: # 只关闭已知系统浮层;保存按钮和 PDD 页面都不重试点击。 self._require_device().press("back") + self._settle_after_address_action() + # 固定稳定等待不能占用原浮层关闭确认超时预算。 + deadline += _ADDRESS_ACTION_SETTLE_SECONDS system_back_attempts = 1 overlay_stable_reads = 0 self._sleep(0.2) diff --git a/client/test/test_pdd_u2_purchase_adapter.py b/client/test/test_pdd_u2_purchase_adapter.py index ed7426a..53f8e40 100644 --- a/client/test/test_pdd_u2_purchase_adapter.py +++ b/client/test/test_pdd_u2_purchase_adapter.py @@ -24,11 +24,13 @@ FIXTURES = Path(__file__).parent / "fixtures" class FakeClock: def __init__(self) -> None: self.now = 0.0 + self.sleeps = [] def monotonic(self) -> float: return self.now def sleep(self, seconds: float) -> None: + self.sleeps.append(seconds) self.now += seconds @@ -952,8 +954,14 @@ class U2PddPurchaseAdapterTest(unittest.TestCase): ) def test_live_adapter_updates_address_and_returns_to_confirmation(self): + clock = FakeClock() device = AddressFlowDevice() - adapter = self._live_adapter(device, []) + adapter = self._live_adapter( + device, + [], + sleeper=clock.sleep, + monotonic=clock.monotonic, + ) adapter.open_goods(GOODS_URL) adapter.select_options( {"color": "黑色", "size": "3XL【140-165斤】"} @@ -970,6 +978,7 @@ class U2PddPurchaseAdapterTest(unittest.TestCase): self.assertEqual(state.page_kind, "order_confirmation") self.assertEqual(state.quantity, 1) self.assertEqual(state.price_cent, 503) + self.assertEqual(clock.sleeps.count(1.0), 5) adapter.close() def test_multiple_addresses_modify_only_default_card(self): @@ -1243,8 +1252,14 @@ class U2PddPurchaseAdapterTest(unittest.TestCase): adapter.close() def test_persistent_coloros_overlay_is_dismissed_with_one_system_back(self): + clock = FakeClock() device = AddressSaveOverlayDevice() - adapter = self._live_adapter(device, []) + adapter = self._live_adapter( + device, + [], + sleeper=clock.sleep, + monotonic=clock.monotonic, + ) adapter.open_goods(GOODS_URL) adapter.select_options( {"color": "黑色", "size": "3XL【140-165斤】"} @@ -1255,6 +1270,7 @@ class U2PddPurchaseAdapterTest(unittest.TestCase): self.assertEqual(device.save_clicks, 1) self.assertEqual(device.presses, ["back"]) self.assertEqual(device.mode, "panel") + self.assertEqual(clock.sleeps.count(1.0), 6) adapter.close() def test_coloros_overlay_is_never_dismissed_more_than_once(self):