import re import time from playwright.sync_api import Playwright, sync_playwright, expect, TimeoutError as PWTimeoutError from utils.auth import login def click_button_until_disappear(frame, button_name="保存提交", interval=5, max_attempts=None, max_duration=None): """ 持续点击按钮直到按钮消失 参数: frame: iframe对象 button_name: 按钮名称 interval: 点击间隔时间(秒) max_attempts: 最大点击次数,None表示不限制 max_duration: 最大持续时间(秒),None表示不限制 返回: dict: 包含点击次数、耗时等信息 """ click_count = 0 start_time = time.time() print(f"开始监控'{button_name}'按钮...") while True: try: # 检查最大点击次数 if max_attempts and click_count >= max_attempts: print(f"已达到最大点击次数{max_attempts}次,停止操作") break # 检查最大持续时间 if max_duration and (time.time() - start_time) >= max_duration: elapsed = time.time() - start_time print(f"已达到最大持续时间{max_duration}秒(实际{elapsed:.1f}秒),停止操作") break button = frame.get_by_role("button", name=button_name) # 检查按钮是否存在 if button.count() == 0: elapsed = time.time() - start_time print(f"'{button_name}'按钮已消失") print(f"共点击{click_count}次,耗时{elapsed:.1f}秒") return { "success": True, "click_count": click_count, "elapsed_time": elapsed } # 点击按钮 button.click() click_count += 1 print(f"[{time.strftime('%H:%M:%S')}] 第{click_count}次点击'{button_name}'") # 等待指定时间 time.sleep(interval) except Exception as e: elapsed = time.time() - start_time print(f"点击过程中出现异常: {e}") return { "success": False, "click_count": click_count, "elapsed_time": elapsed, "error": str(e) } def get_input_by_label(frame, label_text: str, label_locator=None): """ 通过标签文本获取对应的输入框对象 参数: frame: iframe对象 label_text: 标签文本(用于查找和日志输出) label_locator: 可选,已经定位好的标签locator。如果为None,则函数内部查找 返回: 成功:返回输入框的locator对象 失败:返回None """ try: # 如果没有传入label_locator,则根据label_text查找 if label_locator is None: label_locator = frame.locator("div").filter(has_text=re.compile(f"^{label_text}$")).first print(f"找到{label_text}标签") # 向上找到包含标签和输入框的共同父容器 parent_container = label_locator.locator("..") # 父元素 # 在父容器中查找输入框 input_box = parent_container.locator("input").first # 如果父元素中没有,再向上一层 if input_box.count() == 0: print(f"{label_text}: 在父元素中未找到,向上一层查找...") grandparent = parent_container.locator("..") # 祖父元素 input_box = grandparent.locator("input").first # 验证是否找到输入框 if input_box.count() > 0: input_box.wait_for(state="visible", timeout=5000) current_value = input_box.input_value() print(f"✓ {label_text}: {current_value}") print(input_box.count()) return input_box else: print(f"✗ {label_text}: 在父容器中找不到输入框") return None except Exception as e: print(f"✗ {label_text}失败: {e}") return None def run(playwright: Playwright) -> None: # 1. 登录 browser, context, page, main_frame = login( playwright=playwright, username="BLDpengqiangqiang", password="Cqbld123456.", headless=False, ignore_https_errors=True ) # 3. 点击打开“补货安排” main_frame.locator("i").first.click() # 假设是某个新建按钮 with page.expect_popup() as page1_info: main_frame.get_by_title("补货安排", exact=True).click() page1 = page1_info.value # 4. 新页面:等待页面加载完成 + 提取嵌套 iframe print("新页面已打开,正在等待内层 iframe 加载...") page1.wait_for_load_state("domcontentloaded") # 等待 DOM 加载 # 或者更稳:page1.wait_for_load_state("networkidle") # 网络空闲 # 提取外层 forwardFrame outer_frame = page1.locator("#forwardFrame").content_frame # 关键:等待内层 #mainiframe 出现并加载 inner_frame_locator = outer_frame.locator("#mainiframe") inner_frame_locator.wait_for(state="visible", timeout=15000) # 最多等15秒 inner_frame = inner_frame_locator.content_frame # 现在内层 iframe 一定就绪了 print("内层 iframe 已加载完成") textbox = inner_frame.get_by_role("textbox", name="期初标识≠") textbox.fill("") # 直接 fill,不需要 press CapsLock inner_frame.locator("#rc_select_0").fill("关闭") # 输入排产号 textbox = inner_frame.get_by_role("textbox", name="排产号") textbox.fill("R") # 直接 fill,不需要 press CapsLock # 输入日期 inner_frame.get_by_role("textbox", name="单据日期结束日期").click() inner_frame.get_by_text("今日").click() inner_frame.get_by_text("今日").click() # 点击查询按钮 inner_frame.locator(".iconfont.icon-chaxun").click() # 勾选所有合同 inner_frame.get_by_role("row", name="序号").get_by_label("").check() # 获取订单合计数量 # 定位包含“合计:”的元素 summary_locator = inner_frame.get_by_text(re.compile(r"合计:\s*\d+\s*行")) # 获取元素的完整文本 summary_text = summary_locator.inner_text() # 例如 "合计: 135 行" # 用正则提取数字 match = re.search(r"\d+", summary_text) if match: row_count = int(match.group()) print(f"当前总行数:{row_count}") else: print("未匹配到行数") row_count = 0 inner_frame.get_by_role("button").filter(has_text="补货安排").hover() inner_frame.get_by_text("生产订单").click() inner_frame.get_by_role("textbox", name="工厂").fill("10010705") with page1.expect_popup(timeout=60000) as page2_info: inner_frame.get_by_role("button", name="确定(Y)").click() page2=page2_info.value # 新页面:等待页面加载完成 + 提取嵌套 iframe print("新页面已打开,正在等待内层 iframe 加载...") page2.wait_for_load_state("domcontentloaded") # 等待 DOM 加载 # 提取外层 forwardFrame outer_frame = page2.locator("#forwardFrame").content_frame # 关键:等待内层 #mainiframe 出现并加载 inner_frame_locator = outer_frame.locator("#mainiframe") inner_frame_locator.wait_for(state="visible", timeout=15000) # 最多等15秒 inner_frame = inner_frame_locator.content_frame print("内层 iframe 已加载完成") # label_div = inner_frame.locator("div").filter(has_text=re.compile(r"^生产部门$")).first # input_box = label_div.locator("..").locator(".wui-input-close > .wui-input") time.sleep(25) # 等待页面完全加载 # pro_dep_input = get_input_by_label(inner_frame, "生产部门") # if pro_dep_input: # print(pro_dep_input.input_value()) # bill_type_input = get_input_by_label(inner_frame, "订单类型") # if bill_type_input: # print(bill_type_input.input_value()) # pro_SN_input = get_input_by_label(inner_frame, "排产号") # if pro_SN_input: # print(pro_SN_input.input_value()) #result = click_button_until_disappear(inner_frame, "保存提交", interval=5) #print(result) input("操作完成,按回车关闭...") context.close() browser.close() with sync_playwright() as playwright: run(playwright)