diff --git a/client/src/pdd_collect_service.py b/client/src/pdd_collect_service.py index e00a8f9..df7383e 100644 --- a/client/src/pdd_collect_service.py +++ b/client/src/pdd_collect_service.py @@ -1545,13 +1545,20 @@ class PddCollectService: if not candidates: return [] - widest = max(item.bounds[2] - item.bounds[0] for item in candidates) - minimum_width = max(48, int(widest * 0.6)) - complete = [ - item - for item in candidates - if item.bounds[2] - item.bounds[0] >= minimum_width - ] + parents = {child: parent for parent in root.iter() for child in parent} + non_scrollable_panel = _find_non_scrollable_spec_panel(root, parents) + if non_scrollable_panel is not None: + # 新版面板会按文字长度设置按钮宽度。它没有横向滚动视口, + # 短按钮不代表被屏幕边缘截断,因此保留所有安全范围内的节点。 + complete = candidates + else: + widest = max(item.bounds[2] - item.bounds[0] for item in candidates) + minimum_width = max(48, int(widest * 0.6)) + complete = [ + item + for item in candidates + if item.bounds[2] - item.bounds[0] >= minimum_width + ] complete.sort(key=lambda item: ((item.bounds[1] + item.bounds[3]) // 2, item.bounds[0])) rows: list[list[VisibleSpecOption]] = [] @@ -1610,6 +1617,7 @@ class PddCollectService: def _find_option_node(root: ET.Element, target: str) -> Optional[ET.Element]: parents = {child: parent for parent in root.iter() for child in parent} scrollables = [node for node in root.iter("node") if node.get("scrollable") == "true"] + non_scrollable_panel = _find_non_scrollable_spec_panel(root, parents) right_edges = [ bounds[2] for node in root.iter("node") @@ -1627,7 +1635,12 @@ class PddCollectService: continue if not 24 <= center_x <= screen_right - 24: continue - if any(container in _ancestors(node, parents) for container in scrollables): + ancestors = _ancestors(node, parents) + in_scrollable = any(container in ancestors for container in scrollables) + in_non_scrollable_panel = non_scrollable_panel is not None and ( + node is non_scrollable_panel or non_scrollable_panel in ancestors + ) + if in_scrollable or in_non_scrollable_panel: return node return None diff --git a/client/test/test_pdd_collect_service.py b/client/test/test_pdd_collect_service.py index 6ec6886..da58023 100644 --- a/client/test/test_pdd_collect_service.py +++ b/client/test/test_pdd_collect_service.py @@ -430,6 +430,37 @@ class PddCollectParserTest(unittest.TestCase): self.assertEqual(result.raw_price, "¥8.17") self.assertNotIn("确认款式", [item.name for item in result.dimensions]) + def test_non_scrollable_spec_panel_exposes_three_color_rows(self): + service = PddCollectService( + PddDeviceService(lambda _serial: object()), + "USB-001", + "client-001", + ) + + rows = service._visible_color_rows(self.non_scrollable_spec_xml) + + self.assertEqual( + [[item.text for item in row] for row in rows], + [ + ["测试黑色", "测试黑色+网袜"], + ["测试黑色+丝袜", "测试黑色+短袜"], + ["测试黑色+长袜"], + ], + ) + self.assertTrue(all(item.available for row in rows for item in row)) + self.assertTrue(all(item.bounds for row in rows for item in row)) + + def test_clickable_text_outside_spec_panel_is_not_an_option(self): + xml_data = """ + + + + """ + root = ET.fromstring(xml_data) + + self.assertIsNone(PddCollectService._find_option_node(root, "测试黑色")) + def test_wait_accepts_non_scrollable_spec_panel_without_sleep(self): device = FakeCollectDevice(self.home_xml, self.non_scrollable_spec_xml) device.opened_url = "https://mobile.yangkeduo.com/goods.html?goods_id=123"