refactor: improve button navigation logic with proper state detection
- Add button-wrapper element locator for accessing action/navigation buttons - Create dedicated button objects (delete, next material, collapse) - Add _is_button_enabled() method using Playwright's is_enabled() - Replace index-based navigation with button state-driven loop - Add row number change detection to wait for data loading - Simplify navigation logic with explicit button click handling Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -38,6 +38,24 @@ class DiscreteMaterialPlanCleaner:
|
||||
if self.verbose:
|
||||
print(*args, **kwargs)
|
||||
|
||||
def _is_button_enabled(self, button_locator):
|
||||
"""
|
||||
判定按钮是否可用
|
||||
|
||||
Args:
|
||||
button_locator: Playwright Locator 对象
|
||||
|
||||
Returns:
|
||||
bool: True 表示按钮可用,False 表示按钮不可用(有 disabled 属性)
|
||||
"""
|
||||
try:
|
||||
# 使用 Playwright 内置的 is_enabled() 方法
|
||||
# 这个方法会正确检查元素及其父元素的可启用状态
|
||||
return button_locator.is_enabled()
|
||||
except Exception as e:
|
||||
self._print(f"检查按钮状态时出错: {e}")
|
||||
return False
|
||||
|
||||
def get_production_order_numbers(self, production_id_file):
|
||||
"""
|
||||
读取总排号文件并查询数据库获取生产订单号
|
||||
@@ -149,18 +167,17 @@ class DiscreteMaterialPlanCleaner:
|
||||
|
||||
# 提取"详细信息"中的数字
|
||||
detail_element = inner_frame.get_by_text(re.compile(r"^详细信息 \(\d+\)$"))
|
||||
detail_text = detail_element.inner_text()
|
||||
# 使用正则表达式提取括号中的数字
|
||||
match = re.search(r"详细信息 \((\d+)\)", detail_text)
|
||||
match = re.search(r"详细信息 \((\d+)\)", detail_element.inner_text())
|
||||
if match:
|
||||
detail_count = int(match.group(1))
|
||||
self._print(f"详细信息数量: {detail_count}")
|
||||
|
||||
# 提取"备料状态"信息
|
||||
detail_element = inner_frame.get_by_text(re.compile(r"^备料状态:.+$"))
|
||||
detail_text = detail_element.inner_text().replace("\n", "")
|
||||
status_element = inner_frame.get_by_text(re.compile(r"^备料状态:.+$"))
|
||||
status_text = status_element.inner_text().replace("\n", "")
|
||||
# 使用正则表达式提取括号中的数字
|
||||
match = re.search(r"^备料状态:(.+)$", detail_text)
|
||||
match = re.search(r"^备料状态:(.+)$", status_text)
|
||||
if match:
|
||||
detail_status = match.group(1)
|
||||
self._print(f"备料状态: {detail_status}")
|
||||
@@ -180,11 +197,55 @@ class DiscreteMaterialPlanCleaner:
|
||||
child_form.wait_for(state="visible", timeout=5000)
|
||||
self._print(f"父容器 .card-table-side-box 已找到")
|
||||
|
||||
# 获取按钮容器对象
|
||||
button_wrapper = child_form.locator(".button-wrapper")
|
||||
button_wrapper.wait_for(state="visible", timeout=5000)
|
||||
self._print(f"按钮容器 .button-wrapper 已找到")
|
||||
|
||||
# 创建按钮对象
|
||||
# 1. 删行按钮
|
||||
delete_row_button = button_wrapper.get_by_role("button", name="删行")
|
||||
|
||||
# 2. 下一个物料按钮 (class="icon-jiantouyou")
|
||||
next_material_button = button_wrapper.locator(".icon-jiantouyou")
|
||||
|
||||
# 3. 侧拉收起按钮 (class="icon-celashouqi")
|
||||
collapse_button = button_wrapper.locator(".icon-celashouqi")
|
||||
|
||||
last_row_number = None # 用于记录上一个物料的行号,初始值为 None
|
||||
# page2.pause()
|
||||
for id in range(detail_count):
|
||||
id_lable_locator = child_form.get_by_text("序号 " + str(id + 1))
|
||||
id_lable_locator.wait_for(state="visible", timeout=10000)
|
||||
self._print(f"处理 {id_lable_locator.inner_text()} ")
|
||||
while self._is_button_enabled(next_material_button):
|
||||
# 等待页面数据加载完成(带超时机制)
|
||||
max_wait_time = 10 # 最大等待10秒
|
||||
start_time = time.time()
|
||||
|
||||
while True:
|
||||
row_number_locator = (
|
||||
child_form.locator("div")
|
||||
.filter(has_text=re.compile(r"^行号$", re.MULTILINE))
|
||||
.locator("input")
|
||||
.first
|
||||
)
|
||||
row_number = row_number_locator.input_value()
|
||||
|
||||
# 检查行号是否发生变化
|
||||
if row_number != last_row_number:
|
||||
break
|
||||
|
||||
# 检查是否超时
|
||||
if time.time() - start_time > max_wait_time:
|
||||
self._print(f"⚠️ 等待数据加载超时,强制继续 (行号: {row_number})")
|
||||
break
|
||||
|
||||
# 等待后重新检查
|
||||
child_form.wait_for_timeout(500)
|
||||
|
||||
self._print(f"当前行号: {row_number} (上一次: {last_row_number})")
|
||||
|
||||
# ... 后续代码逻辑 ...
|
||||
|
||||
# 处理完当前行后,更新 last_row_number
|
||||
last_row_number = row_number
|
||||
|
||||
# 获取材料编码(用于精确匹配)
|
||||
input_box = (
|
||||
@@ -231,6 +292,13 @@ class DiscreteMaterialPlanCleaner:
|
||||
if should_delete:
|
||||
if not cumulative_pending_quantity :
|
||||
self._print(f"✅ 可以删除")
|
||||
delete_row_button.click()
|
||||
# 使用正则表达式提取括号中的数字
|
||||
match = re.search(r"详细信息 \((\d+)\)", detail_element.inner_text())
|
||||
if match:
|
||||
detail_count = int(match.group(1))
|
||||
self._print(f"详细信息数量: {detail_count}")
|
||||
break
|
||||
else:
|
||||
self._print(f"❌ 累计待发数量不为空,无法删除")
|
||||
self._print(
|
||||
@@ -240,14 +308,15 @@ class DiscreteMaterialPlanCleaner:
|
||||
else:
|
||||
self._print(f"保留:材料名称【{material_name}】材料编码【{material_code}】无需清理")
|
||||
|
||||
if id != detail_count - 1:
|
||||
child_form.get_by_role("button").filter(
|
||||
has_text=re.compile(r"^$")
|
||||
).nth(2).click()
|
||||
# 检查"下一个物料"按钮是否可用
|
||||
if self._is_button_enabled(next_material_button):
|
||||
self._print("按钮可用,可以点击")
|
||||
next_material_button.click()
|
||||
else:
|
||||
child_form.get_by_role("button").filter(
|
||||
has_text=re.compile(r"^$")
|
||||
).nth(4).click()
|
||||
self._print("按钮不可用,有 disabled 属性")
|
||||
|
||||
collapse_button.click()
|
||||
|
||||
# page2.pause()
|
||||
|
||||
elif detail_count == 0:
|
||||
|
||||
Reference in New Issue
Block a user