顺心站点支持双账号(双归属地)下载与融合
- main_router: 顺心在同一窗口开两个标签页登录两个归属地账号;就绪轮询、 初始弹窗、菜单 [1][2]、自动化测试均改为按 page 列表处理 - site_shunxin: download 入口改为接收 page 列表;新增 shunxin_belonging 读归属地、shunxin_merge_final 融合两账号数据;impl 加 out_tag 参数化 各账号产物文件名;两账号同归属地时去重校验中止以防数据翻倍 - expected_undelivered: 零改动(融合后产物仍为同名文件) - 更新 CLAUDE.md / README.md 文档说明 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -125,18 +125,38 @@ def run_automation_test(pages_map):
|
||||
},
|
||||
}
|
||||
|
||||
# 构建测试计划:[(站点, 流程中文名, 流程函数), ...]
|
||||
# 构建测试计划:[(站点, 流程中文名, 流程函数, 绑定page, 归属标签), ...]
|
||||
# 顺心为双账号:两个 page 各自读归属地后跑一遍交叉序列;其余站点单 page。
|
||||
plan = []
|
||||
for site_name, flows in flow_table.items():
|
||||
if site_name == "顺心":
|
||||
if "顺心" not in pages_map:
|
||||
continue
|
||||
for sx_idx, sx_page in enumerate(pages_map["顺心"], start=1):
|
||||
try:
|
||||
tag = site_shunxin.shunxin_belonging(sx_page)
|
||||
except Exception:
|
||||
tag = f"账号{sx_idx}" # 读不到归属地时用序号占位,不阻断测试
|
||||
for flow_key in CROSS_TEST_SEQUENCE:
|
||||
label, func = flows[flow_key]
|
||||
plan.append((f"顺心·{tag}", label, func, sx_page, tag))
|
||||
continue
|
||||
if site_name not in pages_map:
|
||||
continue
|
||||
bound_page = pages_map[site_name]
|
||||
for flow_key in CROSS_TEST_SEQUENCE:
|
||||
label, func = flows[flow_key]
|
||||
plan.append((site_name, label, func))
|
||||
plan.append((site_name, label, func, bound_page, ""))
|
||||
# 百世:单流程,跑一次即可
|
||||
if "百世" in pages_map:
|
||||
plan.append(
|
||||
("百世", "应到未到", site_baishi.baishi_download_undelivered_data_impl)
|
||||
(
|
||||
"百世",
|
||||
"应到未到",
|
||||
site_baishi.baishi_download_undelivered_data_impl,
|
||||
pages_map["百世"],
|
||||
"",
|
||||
)
|
||||
)
|
||||
|
||||
if not plan:
|
||||
@@ -150,7 +170,7 @@ def run_automation_test(pages_map):
|
||||
print("====================================================")
|
||||
|
||||
results = [] # [(站点, 流程, 状态, 耗时秒, 错误信息)]
|
||||
for idx, (site_name, label, func) in enumerate(plan, start=1):
|
||||
for idx, (site_name, label, func, bound_page, out_tag) in enumerate(plan, start=1):
|
||||
print("\n----------------------------------------------------")
|
||||
print(f"[步骤 {idx}/{total}] 站点【{site_name}】流程【{label}】")
|
||||
print("----------------------------------------------------")
|
||||
@@ -162,9 +182,9 @@ def run_automation_test(pages_map):
|
||||
# 安能:Electron 应用,无 Playwright page,函数不收 page 参数
|
||||
ret = func()
|
||||
else:
|
||||
page = pages_map[site_name]
|
||||
page.bring_to_front()
|
||||
ret = func(page)
|
||||
bound_page.bring_to_front()
|
||||
# 顺心 _impl 带 out_tag(归属地);其余站点 _impl 仅收 page
|
||||
ret = func(bound_page, out_tag=out_tag) if out_tag else func(bound_page)
|
||||
if ret is False:
|
||||
status = "FAIL"
|
||||
err = "流程返回失败状态"
|
||||
@@ -252,10 +272,21 @@ def run_multi_site_daemon():
|
||||
print("====================================================")
|
||||
|
||||
for site_name, url in active_sites.items():
|
||||
print(f">> 正在启动【{site_name}】页面: {url}")
|
||||
page = context.new_page()
|
||||
page.goto(url)
|
||||
pages_map[site_name] = page
|
||||
if site_name == "顺心":
|
||||
# 顺心:两个归属地账号在同一窗口各开一个标签页(顺心站点支持
|
||||
# 同浏览器双账号并存);pages_map["顺心"] 存为 page 列表。
|
||||
sx_pages = []
|
||||
for acct in range(1, 3):
|
||||
print(f">> 正在启动【顺心】账号{acct}标签页: {url}")
|
||||
sx_page = context.new_page()
|
||||
sx_page.goto(url)
|
||||
sx_pages.append(sx_page)
|
||||
pages_map["顺心"] = sx_pages
|
||||
else:
|
||||
print(f">> 正在启动【{site_name}】页面: {url}")
|
||||
page = context.new_page()
|
||||
page.goto(url)
|
||||
pages_map[site_name] = page
|
||||
|
||||
# 安能:以调试模式启动 Electron 应用(非 Playwright 网页)
|
||||
anneng_proc = None
|
||||
@@ -296,6 +327,12 @@ def run_multi_site_daemon():
|
||||
if site_name == "安能":
|
||||
# 安能走 CDP 判断主页是否就绪(连不上返回 False,不抛异常)
|
||||
ok = site_anneng.anneng_ready()
|
||||
elif site_name == "顺心":
|
||||
# 顺心双账号:两个 page 都进主页才算就绪
|
||||
ok = all(
|
||||
pg.locator(READY_SELECTORS["顺心"]).is_visible(timeout=500)
|
||||
for pg in pages_map["顺心"]
|
||||
)
|
||||
else:
|
||||
# 0.5 秒轻量探测,避免阻塞主循环
|
||||
ok = (
|
||||
@@ -321,20 +358,20 @@ def run_multi_site_daemon():
|
||||
print("【准备】所有站点已就绪,正在清理初始弹窗...")
|
||||
print("====================================================")
|
||||
|
||||
# 顺心:处理初始弹窗
|
||||
# 顺心:处理初始弹窗(双账号两个 page 各处理一遍)
|
||||
if "顺心" in pages_map:
|
||||
try:
|
||||
sx_page = pages_map["顺心"]
|
||||
sx_page.bring_to_front()
|
||||
print(">> 正在处理【顺心】弹窗与遮罩...")
|
||||
sx_page.locator("a").nth(4).click(timeout=2000)
|
||||
sx_page.wait_for_timeout(500)
|
||||
sx_page.get_by_role("button", name="Close").click(timeout=2000)
|
||||
sx_page.wait_for_timeout(500)
|
||||
sx_page.get_by_role("button", name="不再询问").click(timeout=2000)
|
||||
print(" ✅ 【顺心】初始弹窗处理完成。")
|
||||
except Exception:
|
||||
pass # 环境可能很干净没有弹窗,无视报错
|
||||
for acct, sx_page in enumerate(pages_map["顺心"], start=1):
|
||||
try:
|
||||
sx_page.bring_to_front()
|
||||
print(f">> 正在处理【顺心】账号{acct}弹窗与遮罩...")
|
||||
sx_page.locator("a").nth(4).click(timeout=2000)
|
||||
sx_page.wait_for_timeout(500)
|
||||
sx_page.get_by_role("button", name="Close").click(timeout=2000)
|
||||
sx_page.wait_for_timeout(500)
|
||||
sx_page.get_by_role("button", name="不再询问").click(timeout=2000)
|
||||
print(f" ✅ 【顺心】账号{acct}初始弹窗处理完成。")
|
||||
except Exception:
|
||||
pass # 环境可能很干净没有弹窗,无视报错
|
||||
|
||||
# 百世:循环关闭初始弹窗
|
||||
if "百世" in pages_map:
|
||||
@@ -423,13 +460,9 @@ def run_multi_site_daemon():
|
||||
|
||||
try:
|
||||
if choice == "1" and is_site_ready("顺心"):
|
||||
page = pages_map["顺心"]
|
||||
page.bring_to_front()
|
||||
site_shunxin.shunxin_expected_download(page)
|
||||
site_shunxin.shunxin_expected_download(pages_map["顺心"])
|
||||
elif choice == "2" and is_site_ready("顺心"):
|
||||
page = pages_map["顺心"]
|
||||
page.bring_to_front()
|
||||
site_shunxin.shunxin_actual_download(page)
|
||||
site_shunxin.shunxin_actual_download(pages_map["顺心"])
|
||||
elif choice == "3" and is_site_ready("百世"):
|
||||
page = pages_map["百世"]
|
||||
page.bring_to_front()
|
||||
|
||||
Reference in New Issue
Block a user