- Standardize quote style (single to double quotes) - Improve code formatting consistency - Apply formatting to utilities, GUI components, and tools - Update imports and docstrings for consistency Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
241 lines
8.4 KiB
Python
241 lines
8.4 KiB
Python
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)
|