cardEntry 优先用 PDD 自带的商品名称语义标记,不靠最长文本猜 #321

Open
opened 2026-09-18 17:20:16 +08:00 by ila · 1 comment
Owner

原始需求

用户导出真机订单列表页 purchase_order.xml 后发现:商品标题节点自带 content-desc="商品名称:...",并指出这应该是订单详情的点击入口依据。

事实(用户导出,真机,2026-09-18)

复算现有 cardEntry()(#310/#311 判据)在这份真实数据上的结果:

选中(错): '360度旋转全金属手机支架(一个灰色装),工厂限时折扣(亏本清仓)'  33字
真实标题:   '全金属360手机支架桌面高档懒人通用直播追剧机械折叠平板旋转'          30字

"取同行最长文本"规则在这张卡片上选中了标题下方的 SKU 副标题,而不是标题——因为副标题比标题多 3 个字。

用户指出的 content-desc="商品名称:..." 节点核实为真:

<node text="全金属360手机支架..." content-desc="商品名称:全金属360手机支架..." clickable="false" bounds="[300,836][919,952]" />

顺着这个节点往上找父节点,直接父节点 bounds="[0,836][1080,1100]" clickable="true",包住商品图+标题+价格整行——这是 WebView 挂好的真实链接容器,比现在的"猜文本再算重叠"可靠得多,且能走正常 ACTION_CLICK(当前对不可点节点走的是模拟手势点击)。

方案

cardEntry() 增加优先路径:卡片内找 content-desc 以"商品名称"开头的节点,取它在卡片内最近的可点祖先,仍由 safe() 拦截与禁词节点的几何重叠;找不到标记或找不到安全的可点祖先时,退回现有的"锚定最大商品图 + 同行最长文本"规则(不移除旧路径,作为兼容兜底)。

验收

  • 新增用例:按真机导出的真实节点结构(商品行容器 clickable=true + 标题 content-desc + 比标题更长的 SKU 副标题)构造夹具,cardEntry() 必须返回商品行容器而不是最长文本节点。
  • 禁用语义路径后该用例必须红。
  • 既有全部用例不受影响(无标记的旧夹具仍走兜底路径)。

风险与回退

新路径只在找到标记且找到安全可点祖先时生效,其余情况完全退回旧逻辑,不改变现有行为。回退即删除该优先路径调用与辅助函数。

文档影响

无长期文档影响:未改入口、配置、接口和状态机,属于卡片点击入口选取精度的改进。

## 原始需求 用户导出真机订单列表页 `purchase_order.xml` 后发现:商品标题节点自带 `content-desc="商品名称:..."`,并指出这应该是订单详情的点击入口依据。 ## 事实(用户导出,真机,2026-09-18) 复算现有 `cardEntry()`(#310/#311 判据)在这份真实数据上的结果: ``` 选中(错): '360度旋转全金属手机支架(一个灰色装),工厂限时折扣(亏本清仓)' 33字 真实标题: '全金属360手机支架桌面高档懒人通用直播追剧机械折叠平板旋转' 30字 ``` "取同行最长文本"规则在这张卡片上选中了标题下方的 SKU 副标题,而不是标题——因为副标题比标题多 3 个字。 用户指出的 `content-desc="商品名称:..."` 节点核实为真: ``` <node text="全金属360手机支架..." content-desc="商品名称:全金属360手机支架..." clickable="false" bounds="[300,836][919,952]" /> ``` 顺着这个节点往上找父节点,直接父节点 `bounds="[0,836][1080,1100]"` `clickable="true"`,包住商品图+标题+价格整行——这是 WebView 挂好的真实链接容器,比现在的"猜文本再算重叠"可靠得多,且能走正常 `ACTION_CLICK`(当前对不可点节点走的是模拟手势点击)。 ## 方案 `cardEntry()` 增加优先路径:卡片内找 `content-desc` 以"商品名称"开头的节点,取它在卡片内最近的可点祖先,仍由 `safe()` 拦截与禁词节点的几何重叠;找不到标记或找不到安全的可点祖先时,退回现有的"锚定最大商品图 + 同行最长文本"规则(不移除旧路径,作为兼容兜底)。 ## 验收 - 新增用例:按真机导出的真实节点结构(商品行容器 clickable=true + 标题 content-desc + 比标题更长的 SKU 副标题)构造夹具,`cardEntry()` 必须返回商品行容器而不是最长文本节点。 - 禁用语义路径后该用例必须红。 - 既有全部用例不受影响(无标记的旧夹具仍走兜底路径)。 ## 风险与回退 新路径只在找到标记且找到安全可点祖先时生效,其余情况完全退回旧逻辑,不改变现有行为。回退即删除该优先路径调用与辅助函数。 ## 文档影响 无长期文档影响:未改入口、配置、接口和状态机,属于卡片点击入口选取精度的改进。
Author
Owner

实施

提交 34164a0(deploy-main)。

  • cardEntry() 新增 semanticEntry() 优先路径:找 content-desc 以"商品名称"开头的节点,取其在卡片内最近的可点祖先,仍由 safe() 拦截禁词重叠。
  • 找不到标记或安全祖先时退回既有"最大商品图+同行最长文本"规则。

验证

  • 单测 411 通过 0 失败。
  • 新增用例按真机导出的真实节点结构构造(商品行容器 clickable=true + content-desc 标题 + 比标题长的 SKU 副标题)。
  • 反证:禁用语义路径后该用例变红,确认新增分支被实际执行。
  • 既有全部用例未受影响(无标记的旧夹具走兜底路径,行为不变)。

说明

本工单号原为 #320,因网络重试导致重复建单,#320 已关闭合并到本工单。代码注释中的编号已同步更正为 #321。

另发现:#319 是另一个不相关的既有工单(本地 demo/purchase_order.py 脚本),与本会话此前误用的 #319 占位编号(一个未提交、已 stash 的 staleDetail 修复草稿)冲突,该草稿代码注释里的编号需要在后续提交时更正。

未验证

真机点击 semanticEntry 选中的容器能否正常进入订单详情——待真机回填。

状态:待验收。

## 实施 提交 `34164a0`(deploy-main)。 - `cardEntry()` 新增 `semanticEntry()` 优先路径:找 content-desc 以"商品名称"开头的节点,取其在卡片内最近的可点祖先,仍由 safe() 拦截禁词重叠。 - 找不到标记或安全祖先时退回既有"最大商品图+同行最长文本"规则。 ## 验证 - 单测 411 通过 0 失败。 - 新增用例按真机导出的真实节点结构构造(商品行容器 clickable=true + content-desc 标题 + 比标题长的 SKU 副标题)。 - 反证:禁用语义路径后该用例变红,确认新增分支被实际执行。 - 既有全部用例未受影响(无标记的旧夹具走兜底路径,行为不变)。 ## 说明 本工单号原为 #320,因网络重试导致重复建单,#320 已关闭合并到本工单。代码注释中的编号已同步更正为 #321。 另发现:#319 是另一个不相关的既有工单(本地 `demo/purchase_order.py` 脚本),与本会话此前误用的 #319 占位编号(一个未提交、已 stash 的 staleDetail 修复草稿)冲突,该草稿代码注释里的编号需要在后续提交时更正。 ## 未验证 真机点击 semanticEntry 选中的容器能否正常进入订单详情——待真机回填。 状态:待验收。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OPC/goauto#321