first commit
This commit is contained in:
0
page_objects/__init__.py
Normal file
0
page_objects/__init__.py
Normal file
BIN
page_objects/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
page_objects/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
page_objects/__pycache__/download_tabbar_page.cpython-312.pyc
Normal file
BIN
page_objects/__pycache__/download_tabbar_page.cpython-312.pyc
Normal file
Binary file not shown.
BIN
page_objects/__pycache__/login_page.cpython-312.pyc
Normal file
BIN
page_objects/__pycache__/login_page.cpython-312.pyc
Normal file
Binary file not shown.
BIN
page_objects/__pycache__/measure_tabbar_page.cpython-312.pyc
Normal file
BIN
page_objects/__pycache__/measure_tabbar_page.cpython-312.pyc
Normal file
Binary file not shown.
BIN
page_objects/__pycache__/more_download_page.cpython-312.pyc
Normal file
BIN
page_objects/__pycache__/more_download_page.cpython-312.pyc
Normal file
Binary file not shown.
BIN
page_objects/__pycache__/screenshot_page.cpython-312.pyc
Normal file
BIN
page_objects/__pycache__/screenshot_page.cpython-312.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
page_objects/__pycache__/upload_config_page.cpython-312.pyc
Normal file
BIN
page_objects/__pycache__/upload_config_page.cpython-312.pyc
Normal file
Binary file not shown.
319
page_objects/download_tabbar_page.py
Normal file
319
page_objects/download_tabbar_page.py
Normal file
@@ -0,0 +1,319 @@
|
||||
# 更新基站页面操作
|
||||
# page_objects/download_tabbar_page.py
|
||||
from appium.webdriver.common.appiumby import AppiumBy
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.common.exceptions import TimeoutException, NoSuchElementException, StaleElementReferenceException
|
||||
import logging
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
import globals.ids as ids # 导入元素ID
|
||||
import globals.global_variable as global_variable # 导入全局变量
|
||||
from globals.driver_utils import check_session_valid, reconnect_driver
|
||||
|
||||
class DownloadTabbarPage:
|
||||
def __init__(self, driver, wait, device_id):
|
||||
self.driver = driver
|
||||
self.wait = wait
|
||||
self.device_id = device_id
|
||||
self.logger = logging.getLogger(__name__)
|
||||
# 添加默认的目标日期值
|
||||
self.target_year = 2022
|
||||
self.target_month = 9
|
||||
self.target_day = 22
|
||||
|
||||
def is_download_tabbar_visible(self):
|
||||
"""检查下载标签栏是否可见"""
|
||||
try:
|
||||
return self.driver.find_element(AppiumBy.ID, ids.DOWNLOAD_TABBAR_ID).is_displayed()
|
||||
except NoSuchElementException:
|
||||
self.logger.warning("下载标签栏元素未找到")
|
||||
return False
|
||||
except Exception as e:
|
||||
self.logger.error(f"检查下载标签栏可见性时发生意外错误: {str(e)}")
|
||||
return False
|
||||
|
||||
def click_download_tabbar(self):
|
||||
"""点击下载标签栏"""
|
||||
try:
|
||||
download_tab = self.wait.until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, ids.DOWNLOAD_TABBAR_ID))
|
||||
)
|
||||
download_tab.click()
|
||||
self.logger.info("已点击下载标签栏")
|
||||
|
||||
# 使用显式等待替代固定等待
|
||||
self.wait.until(
|
||||
lambda driver: self.is_download_tabbar_visible()
|
||||
)
|
||||
return True
|
||||
except TimeoutException:
|
||||
self.logger.error("等待下载标签栏可点击超时")
|
||||
return False
|
||||
except Exception as e:
|
||||
self.logger.error(f"点击下载标签栏时出错: {str(e)}")
|
||||
return False
|
||||
|
||||
def update_work_base(self):
|
||||
"""更新工作基点"""
|
||||
try:
|
||||
# 点击更新工作基点
|
||||
update_work_base = self.wait.until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, ids.UPDATE_WORK_BASE))
|
||||
)
|
||||
update_work_base.click()
|
||||
self.logger.info("已点击更新工作基点")
|
||||
|
||||
# 等待更新完成 - 可以添加更具体的等待条件
|
||||
# 例如等待某个进度条消失或成功提示出现
|
||||
time.sleep(2) # 暂时保留,但建议替换为显式等待
|
||||
return True
|
||||
except TimeoutException:
|
||||
self.logger.error("等待更新工作基点按钮可点击超时")
|
||||
return False
|
||||
except Exception as e:
|
||||
self.logger.error(f"更新工作基点时出错: {str(e)}")
|
||||
return False
|
||||
|
||||
def _get_current_date(self):
|
||||
"""获取当前开始日期控件的日期值,支持多种格式解析"""
|
||||
try:
|
||||
date_element = self.wait.until(
|
||||
EC.visibility_of_element_located((AppiumBy.ID, ids.DATE_START))
|
||||
)
|
||||
date_text = date_element.text.strip()
|
||||
self.logger.info(f"获取到当前开始日期: {date_text}")
|
||||
|
||||
# 尝试多种日期格式解析
|
||||
date_formats = [
|
||||
"%Y-%m-%d", # 匹配 '2025-08-12' 格式
|
||||
"%Y年%m月%d日", # 匹配 '2025年08月12日' 格式
|
||||
"%Y/%m/%d" # 可选:添加其他可能的格式
|
||||
]
|
||||
|
||||
for fmt in date_formats:
|
||||
try:
|
||||
return datetime.strptime(date_text, fmt)
|
||||
except ValueError:
|
||||
continue # 尝试下一种格式
|
||||
|
||||
# 如果所有格式都匹配失败
|
||||
self.logger.error(f"日期格式解析错误: 无法识别的格式,日期文本: {date_text}")
|
||||
return None
|
||||
|
||||
except TimeoutException:
|
||||
self.logger.error("获取当前日期超时")
|
||||
return None
|
||||
except Exception as e:
|
||||
self.logger.error(f"获取当前日期失败: {str(e)}")
|
||||
return None
|
||||
|
||||
def update_level_line(self):
|
||||
"""更新水准线路,修改为设置2022年9月22日"""
|
||||
try:
|
||||
# 点击更新水准线路
|
||||
update_level_line = self.wait.until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, ids.UPDATE_LEVEL_LINE))
|
||||
)
|
||||
update_level_line.click()
|
||||
self.logger.info("已点击更新水准线路")
|
||||
|
||||
# 获取原始开始日期
|
||||
original_date = self._get_current_date()
|
||||
if not original_date:
|
||||
self.logger.error("无法获取原始开始日期,更新水准线路失败")
|
||||
return False
|
||||
|
||||
# 点击开始日期
|
||||
date_start = self.wait.until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, ids.DATE_START))
|
||||
)
|
||||
date_start.click()
|
||||
self.logger.info("已点击开始日期控件")
|
||||
|
||||
# 处理时间选择器,设置为2022年9月22日
|
||||
if not self.handle_time_selector(2022, 9, 22, original_date):
|
||||
self.logger.error("处理时间选择失败")
|
||||
return False
|
||||
|
||||
return True
|
||||
except TimeoutException:
|
||||
self.logger.error("等待更新水准线路按钮可点击超时")
|
||||
return False
|
||||
except Exception as e:
|
||||
self.logger.error(f"更新水准线路时出错: {str(e)}")
|
||||
return False
|
||||
|
||||
def _scroll_to_value(self, picker_id, target_value, original_value, max_attempts=20):
|
||||
"""滚动选择器到目标值,基于原始值计算滚动次数"""
|
||||
try:
|
||||
# 计算需要滚动的次数(绝对值)
|
||||
scroll_count = abs(int(target_value) - int(original_value))
|
||||
self.logger.info(f"需要滚动{scroll_count}次将{picker_id}从{original_value}调整到{target_value}")
|
||||
|
||||
# 确定滚动方向
|
||||
direction = "down" if int(target_value) > int(original_value) else "up"
|
||||
|
||||
# 获取选择器元素
|
||||
picker = self.wait.until(
|
||||
EC.visibility_of_element_located((AppiumBy.ID, picker_id))
|
||||
)
|
||||
|
||||
# 计算滚动坐标
|
||||
x = picker.location['x'] + picker.size['width'] // 2
|
||||
self.logger.info(f"水平位置x为{x}")
|
||||
y_center = picker.location['y'] + picker.size['height'] // 2
|
||||
self.logger.info(f"垂直位置中点y_center为{y_center}")
|
||||
# start_y = y_center if direction == "down" else picker.location['y']
|
||||
# end_y = picker.location['y'] if direction == "down" else y_center
|
||||
# 关键修改:计算选择器高度的五分之一(滑动距离)
|
||||
height_fifth = picker.size['height'] // 5 # 1/5高度
|
||||
|
||||
# 根据方向计算起点和终点,确保滑动距离为 height_fifth
|
||||
if direction == "down":
|
||||
# 向下滚动:从中心点向上滑动1/5高度
|
||||
start_y = y_center
|
||||
end_y = y_center - height_fifth # 终点 = 中心点 - 1/5高度
|
||||
self.logger.info(f"down垂直开始位置start_y为{y_center},垂直结束位置end_y为{end_y}")
|
||||
|
||||
else:
|
||||
# 向上滚动:从中心点向下滑动1/5高度
|
||||
start_y = y_center
|
||||
end_y = y_center + height_fifth # 终点 = 中心点 + 1/5高度
|
||||
self.logger.info(f"up垂直开始位置start_y为{y_center},垂直结束位置end_y为{end_y}")
|
||||
# 执行滚动操作
|
||||
for _ in range(scroll_count):
|
||||
self.driver.swipe(x, start_y, x, end_y, 500)
|
||||
time.sleep(0.5) # 等待滚动稳定
|
||||
return True # 循环scroll_count次后直接返回
|
||||
# # 验证当前值
|
||||
# current_value = picker.text
|
||||
# if current_value == str(target_value):
|
||||
# self.logger.info(f"{picker_id}已达到目标值: {target_value}")
|
||||
# return True
|
||||
|
||||
# 最终验证
|
||||
# final_value = picker.text
|
||||
# if final_value == str(target_value):
|
||||
# self.logger.info(f"{picker_id}已达到目标值: {target_value}")
|
||||
# return True
|
||||
# else:
|
||||
# self.logger.error(f"{picker_id}滚动{scroll_count}次后未达到目标值,当前值: {final_value}")
|
||||
# return False
|
||||
|
||||
except StaleElementReferenceException:
|
||||
self.logger.warning("元素状态已过期,重新获取")
|
||||
return False
|
||||
except Exception as e:
|
||||
self.logger.error(f"滚动选择器出错: {str(e)}")
|
||||
return False
|
||||
|
||||
def handle_time_selector(self, target_year, target_month, target_day, original_date=None):
|
||||
"""处理时间选择器,选择起始时间并确认"""
|
||||
self.logger.info(f"传入handle_time_selector的初始日期: {original_date}")
|
||||
try:
|
||||
# 等待时间选择器出现
|
||||
self.wait.until(
|
||||
EC.visibility_of_element_located((AppiumBy.ID, ids.ALERT_DIALOG))
|
||||
)
|
||||
self.logger.info("时间选择对话框已出现")
|
||||
|
||||
# 如果没有提供原始日期,使用当前日期控件的值
|
||||
if not original_date:
|
||||
original_date = self._get_current_date()
|
||||
if not original_date:
|
||||
self.logger.error("无法获取原始日期,处理时间选择失败")
|
||||
return False
|
||||
|
||||
# 滚动选择年份
|
||||
if not self._scroll_to_value(ids.SCRCOLL_YEAR, target_year, original_date.year):
|
||||
self.logger.error("滚动选择年份失败")
|
||||
return False
|
||||
|
||||
# 滚动选择月份
|
||||
if not self._scroll_to_value(ids.SCRCOLL_MONTH, target_month, original_date.month):
|
||||
self.logger.error("滚动选择月份失败")
|
||||
return False
|
||||
|
||||
# 滚动选择日期
|
||||
if not self._scroll_to_value(ids.SCRCOLL_DAY, target_day, original_date.day):
|
||||
self.logger.error("滚动选择日期失败")
|
||||
return False
|
||||
|
||||
# 点击确认按钮
|
||||
confirm_btn = self.wait.until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, ids.SCRCOLL_CONFIRM)) # 日期选择器确认按钮
|
||||
)
|
||||
confirm_btn.click()
|
||||
self.logger.info("已确认时间选择")
|
||||
|
||||
# 点击对话框确认按钮(UPDATE_LEVEL_LINE_CONFIRM)
|
||||
confirm_btn = self.wait.until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, ids.UPDATE_LEVEL_LINE_CONFIRM)) # 选择日期对话框确认按钮
|
||||
)
|
||||
confirm_btn.click()
|
||||
self.logger.info("已点击对话框确认按钮commit")
|
||||
|
||||
# 新增:等待加载对话框出现
|
||||
custom_dialog = self.wait.until(
|
||||
EC.visibility_of_element_located((AppiumBy.ID, ids.LOADING_DIALOG))
|
||||
)
|
||||
self.logger.info("检测到loading对话框出现")
|
||||
|
||||
if not check_session_valid(self.driver, self.device_id):
|
||||
self.logger.warning(f"设备 {self.device_id} 会话无效,尝试重新连接驱动...")
|
||||
if not reconnect_driver(self.device_id, self.driver):
|
||||
self.logger.error(f"设备 {self.device_id} 驱动重连失败")
|
||||
|
||||
# 新增:等待加载对话框消失(表示更新完成)
|
||||
WebDriverWait(self.driver, 300).until(
|
||||
EC.invisibility_of_element_located((AppiumBy.ID, ids.LOADING_DIALOG))
|
||||
)
|
||||
self.logger.info("loading对话框已消失,更新完成")
|
||||
|
||||
'''点击commit确认按钮后,loading弹窗会出现,等待其加载完成后关闭
|
||||
检测导航栏中的测量tabbar是否出现来确定是否返回True
|
||||
'''
|
||||
# measure_tabbar_btn = self.wait.until(
|
||||
# EC.visibility_of_element_located((AppiumBy.ID, ids.MEASURE_TABBAR_ID))
|
||||
# )
|
||||
# self.logger.info("检测测量tabbar按钮出现")
|
||||
|
||||
return True
|
||||
|
||||
except TimeoutException as e:
|
||||
# 明确超时发生在哪个环节
|
||||
self.logger.error("处理时间选择时超时:可能是等待对话框出现、日期选择器元素或确认按钮超时", exc_info=True)
|
||||
return False
|
||||
except Exception as e:
|
||||
# 细分不同环节的异常
|
||||
self.logger.error(f"处理时间选择对话框时出错:可能是日期滚动、选择器确认或对话框确认环节失败 - {str(e)}", exc_info=True)
|
||||
return False
|
||||
|
||||
def download_tabbar_page_manager(self):
|
||||
"""执行基础更新操作"""
|
||||
try:
|
||||
# 执行基础更新流程
|
||||
self.logger.info(f"设备 {global_variable.get_device_id()} 开始执行更新流程")
|
||||
|
||||
# 点击下载标签栏
|
||||
if not self.click_download_tabbar():
|
||||
self.logger.error(f"设备 {global_variable.get_device_id()} 点击下载标签栏失败")
|
||||
return False
|
||||
|
||||
# 更新工作基点
|
||||
if not self.update_work_base():
|
||||
self.logger.error(f"设备 {global_variable.get_device_id()} 更新工作基点失败")
|
||||
return False
|
||||
|
||||
# 更新水准线路
|
||||
if not self.update_level_line():
|
||||
self.logger.error(f"设备 {global_variable.get_device_id()} 更新水准线路失败")
|
||||
return False
|
||||
|
||||
self.logger.info(f"设备 {global_variable.get_device_id()} 更新操作执行成功")
|
||||
return True
|
||||
except Exception as e:
|
||||
self.logger.error(f"设备 {global_variable.get_device_id()} 执行更新操作时出错: {str(e)}")
|
||||
return False
|
||||
116
page_objects/login_page.py
Normal file
116
page_objects/login_page.py
Normal file
@@ -0,0 +1,116 @@
|
||||
# 登录页面操作
|
||||
# page_objects/login_page.py
|
||||
from appium.webdriver.common.appiumby import AppiumBy
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.common.exceptions import TimeoutException, NoSuchElementException
|
||||
import logging
|
||||
import time
|
||||
import globals.apis as apis
|
||||
|
||||
import globals.ids as ids
|
||||
import globals.global_variable as global_variable # 导入全局变量模块
|
||||
|
||||
class LoginPage:
|
||||
def __init__(self, driver, wait):
|
||||
self.driver = driver
|
||||
self.wait = wait
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
def is_login_page(self):
|
||||
"""检查当前是否为登录页面"""
|
||||
try:
|
||||
return self.driver.find_element(AppiumBy.ID, ids.LOGIN_BTN).is_displayed()
|
||||
except NoSuchElementException:
|
||||
return False
|
||||
|
||||
def login(self):
|
||||
"""执行登录操作"""
|
||||
try:
|
||||
self.logger.info("正在执行登录操作...")
|
||||
|
||||
# 获取文本框中已有的用户名
|
||||
username_field = self.wait.until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, ids.LOGIN_USERNAME))
|
||||
)
|
||||
|
||||
# 读取文本框内已有的用户名(.text属性获取元素显示的文本内容)
|
||||
existing_username = username_field.text
|
||||
# 3. 将获取到的用户名写入全局变量中
|
||||
# global_variable.GLOBAL_USERNAME = existing_username # 关键:给全局变量赋值
|
||||
global_variable.set_username(existing_username)
|
||||
|
||||
# 日志记录获取到的已有用户名(若为空,也需明确记录,避免后续误解)
|
||||
if existing_username.strip(): # 去除空格后判断是否有有效内容
|
||||
self.logger.info(f"已获取文本框中的已有用户名: {existing_username}")
|
||||
else:
|
||||
self.logger.info("文本框中未检测到已有用户名(内容为空)")
|
||||
|
||||
# 1. 定位密码输入框
|
||||
password_field = self.wait.until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, ids.LOGIN_PASSWORD))
|
||||
)
|
||||
|
||||
# 2. 清空密码框(如果需要)
|
||||
try:
|
||||
password_field.clear()
|
||||
# time.sleep(0.5) # 等待清除完成
|
||||
except:
|
||||
# 如果clear方法不可用,尝试其他方式
|
||||
pass
|
||||
|
||||
accounts = apis.get_accounts_from_server("68c0dbfdb7cbcd616e7c5ab5")
|
||||
matches = [acc for acc in accounts if acc.get("username") == existing_username]
|
||||
if matches:
|
||||
password = matches[0].get("password")
|
||||
|
||||
password_field.send_keys(password)
|
||||
|
||||
# 4. 可选:隐藏键盘
|
||||
try:
|
||||
self.driver.hide_keyboard()
|
||||
except:
|
||||
pass
|
||||
|
||||
# 点击登录按钮
|
||||
max_retries = 3
|
||||
retry_count = 0
|
||||
|
||||
while retry_count < max_retries:
|
||||
login_btn = self.wait.until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, ids.LOGIN_BTN))
|
||||
)
|
||||
login_btn.click()
|
||||
self.logger.info(f"已点击登录按钮 (尝试 {retry_count + 1}/{max_retries})")
|
||||
|
||||
# 等待登录完成
|
||||
time.sleep(3)
|
||||
|
||||
# 检查是否登录成功
|
||||
if self.is_login_successful():
|
||||
self.logger.info("登录成功")
|
||||
return True
|
||||
else:
|
||||
self.logger.warning("登录后未检测到主页面元素,准备重试")
|
||||
retry_count += 1
|
||||
if retry_count < max_retries:
|
||||
self.logger.info(f"等待2秒后重新尝试登录...")
|
||||
time.sleep(2)
|
||||
|
||||
self.logger.error(f"登录失败,已尝试 {max_retries} 次")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"登录过程中出错: {str(e)}")
|
||||
return False
|
||||
|
||||
def is_login_successful(self):
|
||||
"""检查登录是否成功"""
|
||||
try:
|
||||
# 等待主页面元素出现
|
||||
self.wait.until(
|
||||
EC.presence_of_element_located((AppiumBy.ID, ids.DOWNLOAD_TABBAR_ID))
|
||||
)
|
||||
return True
|
||||
except TimeoutException:
|
||||
return False
|
||||
506
page_objects/more_download_page.py
Normal file
506
page_objects/more_download_page.py
Normal file
@@ -0,0 +1,506 @@
|
||||
# test_more_download_page.py
|
||||
from appium.webdriver.common.appiumby import AppiumBy
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.common.exceptions import TimeoutException, NoSuchElementException
|
||||
import logging
|
||||
import time
|
||||
from globals.driver_utils import launch_app_manually
|
||||
from page_objects.login_page import LoginPage
|
||||
|
||||
class MoreDownloadPage:
|
||||
def __init__(self, driver, wait,device_id):
|
||||
self.driver = driver
|
||||
self.wait = wait
|
||||
self.device_id = device_id
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
def is_on_more_download_page(self):
|
||||
"""通过下载历史数据按钮来判断是否在更多下载页面"""
|
||||
try:
|
||||
# 使用下载历史数据按钮的resource-id来检查
|
||||
download_history_locator = (AppiumBy.ID, "com.bjjw.cjgc:id/download_history")
|
||||
self.wait.until(EC.presence_of_element_located(download_history_locator))
|
||||
self.logger.info("已确认在更多下载页面")
|
||||
return True
|
||||
except TimeoutException:
|
||||
self.logger.warning("未找到下载历史数据按钮,不在更多下载页面")
|
||||
return False
|
||||
except Exception as e:
|
||||
self.logger.error(f"检查更多下载页面时发生意外错误: {str(e)}")
|
||||
return False
|
||||
|
||||
def click_download_button(self):
|
||||
"""点击下载按钮"""
|
||||
try:
|
||||
# 点击下载历史数据按钮
|
||||
download_button = self.wait.until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, "com.bjjw.cjgc:id/download_history"))
|
||||
)
|
||||
download_button.click()
|
||||
self.logger.info("已点击下载历史数据按钮")
|
||||
|
||||
# 等待下载操作开始
|
||||
# time.sleep(3)
|
||||
|
||||
return True
|
||||
|
||||
except TimeoutException:
|
||||
self.logger.error("等待下载按钮可点击超时")
|
||||
return False
|
||||
except Exception as e:
|
||||
self.logger.error(f"点击下载按钮时出错: {str(e)}")
|
||||
return False
|
||||
|
||||
def click_download_original_data(self):
|
||||
"""点击下载原始数据按钮并处理日期选择"""
|
||||
try:
|
||||
# 点击下载原始数据按钮
|
||||
download_original_btn = self.wait.until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, "com.bjjw.cjgc:id/download_org"))
|
||||
)
|
||||
download_original_btn.click()
|
||||
self.logger.info("已点击下载原始数据按钮")
|
||||
|
||||
# 等待日期选择弹窗出现
|
||||
# time.sleep(2)
|
||||
|
||||
# 点击选择开始日期
|
||||
start_date_btn = self.wait.until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, "com.bjjw.cjgc:id/date"))
|
||||
)
|
||||
start_date_btn.click()
|
||||
self.logger.info("已点击选择开始日期")
|
||||
|
||||
# 等待日期选择器出现
|
||||
# time.sleep(2)
|
||||
|
||||
# 滑动年份选择器 - 向上滑动1/5的距离
|
||||
if not self._swipe_year_wheel():
|
||||
self.logger.error("滑动年份选择器失败")
|
||||
return False
|
||||
|
||||
# 点击日期选择器的确定按钮
|
||||
confirm_btn = self.wait.until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, "com.bjjw.cjgc:id/okBtn"))
|
||||
)
|
||||
confirm_btn.click()
|
||||
self.logger.info("已确认日期选择")
|
||||
|
||||
# 等待日期选择器关闭
|
||||
# time.sleep(2)
|
||||
|
||||
# 假设弹窗有确定按钮,点击它开始下载
|
||||
try:
|
||||
# 尝试查找并点击下载弹窗的确定按钮
|
||||
download_confirm_btn = WebDriverWait(self.driver, 5).until(
|
||||
EC.element_to_be_clickable((AppiumBy.XPATH, "//android.widget.Button[contains(@text, '确定') or contains(@text, '下载')]"))
|
||||
)
|
||||
download_confirm_btn.click()
|
||||
self.logger.info("已点击下载确认按钮")
|
||||
except TimeoutException:
|
||||
self.logger.warning("未找到下载确认按钮,可能不需要确认")
|
||||
|
||||
# 等待下载开始
|
||||
# time.sleep(3)
|
||||
|
||||
return True
|
||||
|
||||
except TimeoutException:
|
||||
self.logger.error("等待下载原始数据按钮可点击超时")
|
||||
return False
|
||||
except Exception as e:
|
||||
self.logger.error(f"点击下载原始数据时出错: {str(e)}")
|
||||
return False
|
||||
|
||||
def click_download_result_data(self):
|
||||
"""点击下载成果数据按钮并处理日期选择"""
|
||||
try:
|
||||
# 点击下载成果数据按钮
|
||||
download_result_btn = self.wait.until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, "com.bjjw.cjgc:id/download_result"))
|
||||
)
|
||||
download_result_btn.click()
|
||||
self.logger.info("已点击下载成果数据按钮")
|
||||
|
||||
# 等待日期选择弹窗出现
|
||||
# time.sleep(2)
|
||||
|
||||
# 点击选择开始日期
|
||||
start_date_btn = self.wait.until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, "com.bjjw.cjgc:id/date"))
|
||||
)
|
||||
start_date_btn.click()
|
||||
self.logger.info("已点击选择开始日期")
|
||||
|
||||
# 等待日期选择器出现
|
||||
# time.sleep(2)
|
||||
|
||||
# 滑动年份选择器 - 向上滑动1/5的距离
|
||||
if not self._swipe_year_wheel():
|
||||
self.logger.error("滑动年份选择器失败")
|
||||
return False
|
||||
|
||||
# 点击日期选择器的确定按钮
|
||||
confirm_btn = self.wait.until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, "com.bjjw.cjgc:id/okBtn"))
|
||||
)
|
||||
confirm_btn.click()
|
||||
self.logger.info("已确认日期选择")
|
||||
|
||||
# 等待日期选择器关闭
|
||||
# time.sleep(2)
|
||||
|
||||
# 假设弹窗有确定按钮,点击它开始下载
|
||||
try:
|
||||
# 尝试查找并点击下载弹窗的确定按钮
|
||||
download_confirm_btn = WebDriverWait(self.driver, 5).until(
|
||||
EC.element_to_be_clickable((AppiumBy.XPATH, "//android.widget.Button[contains(@text, '确定') or contains(@text, '下载')]"))
|
||||
)
|
||||
download_confirm_btn.click()
|
||||
self.logger.info("已点击下载确认按钮")
|
||||
except TimeoutException:
|
||||
self.logger.warning("未找到下载确认按钮,可能不需要确认")
|
||||
|
||||
# 等待下载开始
|
||||
# time.sleep(3)
|
||||
|
||||
return True
|
||||
|
||||
except TimeoutException:
|
||||
self.logger.error("等待下载成果数据按钮可点击超时")
|
||||
return False
|
||||
except Exception as e:
|
||||
self.logger.error(f"点击下载成果数据时出错: {str(e)}")
|
||||
return False
|
||||
|
||||
def _swipe_year_wheel(self):
|
||||
"""滑动年份选择器的滚轮"""
|
||||
try:
|
||||
# 获取年份选择器滚轮元素
|
||||
year_wheel = self.driver.find_element(AppiumBy.ID, "com.bjjw.cjgc:id/wheelView2")
|
||||
|
||||
# 获取滚轮的位置和尺寸
|
||||
location = year_wheel.location
|
||||
size = year_wheel.size
|
||||
|
||||
# 计算滚轮中心点坐标
|
||||
center_x = location['x'] + size['width'] // 2
|
||||
center_y = location['y'] + size['height'] // 2
|
||||
|
||||
# 计算滑动距离 - 滚轮高度的1/5
|
||||
swipe_distance = size['height'] // 5
|
||||
|
||||
for i in range(3):
|
||||
# 执行滑动操作 - 从中心向上滑动1/5高度
|
||||
self.driver.swipe(center_x, center_y - swipe_distance, center_x, center_y, 500)
|
||||
|
||||
self.logger.info(f"已{i}次滑动月份选择器")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"滑动年份选择器时出错: {str(e)}")
|
||||
return False
|
||||
|
||||
# def wait_for_loading_dialog(self, timeout=900, download_type="unknown"):
|
||||
# """
|
||||
# 检查特定结构的加载弹窗的出现和消失
|
||||
|
||||
# 参数:
|
||||
# timeout: 最大等待时间,默认10分钟(600秒)
|
||||
|
||||
# 返回:
|
||||
# bool: 如果加载弹窗出现并消失返回True,否则返回False
|
||||
# """
|
||||
# try:
|
||||
# self.logger.info(f"开始检查{download_type}加载弹窗...")
|
||||
|
||||
# # 首先检查加载弹窗是否出现
|
||||
# start_time = time.time()
|
||||
# loading_appeared = False
|
||||
|
||||
# # 等待加载弹窗出现(最多等待30秒)
|
||||
# while time.time() - start_time < 30:
|
||||
# try:
|
||||
# # 根据提供的结构查找加载弹窗
|
||||
# # 查找包含ProgressBar和"loading..."文本的弹窗
|
||||
# loading_indicators = [
|
||||
# (AppiumBy.XPATH, "//android.widget.FrameLayout[@resource-id='android:id/content']/android.widget.LinearLayout[@resource-id='android:id/parentPanel']//android.widget.ProgressBar"),
|
||||
# (AppiumBy.XPATH, "//android.widget.TextView[@resource-id='android:id/message' and @text='loading...']"),
|
||||
# (AppiumBy.XPATH, "//android.widget.FrameLayout[@resource-id='android:id/content']//android.widget.ProgressBar"),
|
||||
# (AppiumBy.XPATH, "//*[contains(@text, 'loading...')]")
|
||||
# ]
|
||||
|
||||
# for by, value in loading_indicators:
|
||||
# try:
|
||||
# element = self.driver.find_element(by, value)
|
||||
# if element.is_displayed():
|
||||
# loading_appeared = True
|
||||
# self.logger.info("数据下载已开始")
|
||||
# self.logger.info("检测到加载弹窗出现")
|
||||
# break
|
||||
# except:
|
||||
# continue
|
||||
|
||||
# if loading_appeared:
|
||||
# break
|
||||
|
||||
# except Exception as e:
|
||||
# pass
|
||||
|
||||
# time.sleep(1)
|
||||
|
||||
# # 如果加载弹窗没有出现,直接返回True
|
||||
# if not loading_appeared:
|
||||
# self.logger.info("未检测到加载弹窗,继续执行")
|
||||
# return True
|
||||
|
||||
# # 等待加载弹窗消失
|
||||
# self.logger.info("等待加载弹窗消失...")
|
||||
# disappearance_start_time = time.time()
|
||||
|
||||
# while time.time() - disappearance_start_time < timeout:
|
||||
# try:
|
||||
# # 检查加载弹窗是否还存在
|
||||
# loading_still_exists = False
|
||||
|
||||
# for by, value in loading_indicators:
|
||||
# try:
|
||||
# element = self.driver.find_element(by, value)
|
||||
# if element.is_displayed():
|
||||
# loading_still_exists = True
|
||||
# break
|
||||
# except:
|
||||
# continue
|
||||
|
||||
# if not loading_still_exists:
|
||||
# self.logger.info("加载弹窗已消失")
|
||||
# return True
|
||||
|
||||
# # 每1分钟记录一次状态
|
||||
# if int(time.time() - disappearance_start_time) % 60 == 0:
|
||||
# elapsed_time = int(time.time() - disappearance_start_time)
|
||||
# self.logger.info(f"加载弹窗仍在显示,已等待{elapsed_time//60}分钟")
|
||||
|
||||
# except Exception as e:
|
||||
# # 如果出现异常,可能弹窗已经消失
|
||||
# self.logger.info("加载弹窗可能已消失")
|
||||
# return True
|
||||
|
||||
# time.sleep(1)
|
||||
|
||||
# # 如果超时,记录错误并返回False
|
||||
# self.logger.error(f"加载弹窗在{timeout}秒后仍未消失")
|
||||
# # return False
|
||||
# # 检查是否有loading加载窗口
|
||||
# try:
|
||||
# self.logger.info(f"检查{download_type}下载是否有loading加载窗口...")
|
||||
# loading_indicators = [
|
||||
# (AppiumBy.XPATH, "//android.widget.FrameLayout[@resource-id='android:id/content']/android.widget.LinearLayout[@resource-id='android:id/parentPanel']//android.widget.ProgressBar"),
|
||||
# (AppiumBy.XPATH, "//android.widget.TextView[@resource-id='android:id/message' and @text='loading...']"),
|
||||
# (AppiumBy.XPATH, "//android.widget.FrameLayout[@resource-id='android:id/content']//android.widget.ProgressBar"),
|
||||
# (AppiumBy.XPATH, "//*[contains(@text, 'loading...')]")
|
||||
# ]
|
||||
|
||||
# loading_exists = False
|
||||
# for by, value in loading_indicators:
|
||||
# try:
|
||||
# element = self.driver.find_element(by, value)
|
||||
# if element.is_displayed():
|
||||
# loading_exists = True
|
||||
# break
|
||||
# except:
|
||||
# continue
|
||||
|
||||
# if loading_exists:
|
||||
# self.logger.info(f"检测到{download_type}下载的loading加载窗口,执行重新打开应用操作")
|
||||
|
||||
|
||||
# # 手动启动应用
|
||||
# launch_app_manually(self.driver, self.device_id, "com.bjjw.cjgc", ".activity.LoginActivity")
|
||||
# self.logger.info("已重新启动沉降观测应用")
|
||||
|
||||
# # 点击登录
|
||||
# login_page = LoginPage(self.driver, self.wait)
|
||||
# if login_page.is_login_page():
|
||||
# if login_page.login():
|
||||
# self.logger.info("登录成功")
|
||||
# else:
|
||||
# self.logger.error("登录失败")
|
||||
# return False
|
||||
# else:
|
||||
# self.logger.info("应用已登录,无需重复登录")
|
||||
|
||||
# self.logger.info(f"{download_type}下载超时处理完成,应用已重启")
|
||||
# # 点击img_5_layout(更多下载按钮)
|
||||
# more_download_btn = self.wait.until(
|
||||
# EC.element_to_be_clickable((AppiumBy.ID, "com.bjjw.cjgc:id/img_5_layout"))
|
||||
# )
|
||||
# more_download_btn.click()
|
||||
# self.logger.info("已点击更多下载按钮")
|
||||
# self.more_download_page_manager_2(download_type)
|
||||
# # 等待页面加载
|
||||
# time.sleep(1)
|
||||
# else:
|
||||
# self.logger.info(f"未检测到{download_type}下载的loading加载窗口")
|
||||
# except Exception as e:
|
||||
# self.logger.error(f"检查{download_type}下载的loading加载窗口时出错: {str(e)}")
|
||||
# # 出错时继续执行,不影响主流程
|
||||
|
||||
# return False
|
||||
|
||||
# except Exception as e:
|
||||
# self.logger.error(f"检查加载弹窗时出错: {str(e)}")
|
||||
# return False
|
||||
|
||||
def _is_loading_present(self):
|
||||
"""私有辅助方法:检测当前页面是否存在加载弹窗"""
|
||||
loading_indicators = [
|
||||
(AppiumBy.XPATH, "//android.widget.FrameLayout[@resource-id='android:id/content']//android.widget.ProgressBar"),
|
||||
(AppiumBy.XPATH, "//android.widget.TextView[@resource-id='android:id/message' and @text='loading...']"),
|
||||
(AppiumBy.XPATH, "//*[contains(@text, 'loading...')]")
|
||||
]
|
||||
for by, value in loading_indicators:
|
||||
try:
|
||||
element = self.driver.find_element(by, value)
|
||||
if element.is_displayed():
|
||||
return True
|
||||
except:
|
||||
continue
|
||||
return False
|
||||
|
||||
def wait_for_loading_dialog(self, timeout=900, download_type="unknown", retry_count=0):
|
||||
"""
|
||||
检查加载弹窗的出现和消失,支持最多1次重试(总共执行2次)
|
||||
"""
|
||||
try:
|
||||
self.logger.info(f"开始检查 {download_type} 加载弹窗 (尝试次数: {retry_count + 1})...")
|
||||
|
||||
# 1. 等待加载弹窗出现(最多30秒)
|
||||
start_time = time.time()
|
||||
loading_appeared = False
|
||||
while time.time() - start_time < 30:
|
||||
if self._is_loading_present():
|
||||
loading_appeared = True
|
||||
self.logger.info(f"检测到 {download_type} 加载弹窗出现")
|
||||
break
|
||||
time.sleep(1)
|
||||
|
||||
if not loading_appeared:
|
||||
self.logger.info(f"未检测到 {download_type} 加载弹窗,视为直接通过")
|
||||
return True
|
||||
|
||||
# 2. 等待加载弹窗消失
|
||||
disappearance_start_time = time.time()
|
||||
while time.time() - disappearance_start_time < timeout:
|
||||
if not self._is_loading_present():
|
||||
self.logger.info(f"{download_type} 加载弹窗已消失")
|
||||
return True
|
||||
|
||||
# 每60秒打印一次日志
|
||||
if int(time.time() - disappearance_start_time) % 60 == 0:
|
||||
self.logger.info(f"等待中...已耗时 {int(time.time() - disappearance_start_time)//60} 分钟")
|
||||
time.sleep(2)
|
||||
|
||||
# 3. 超时处理逻辑
|
||||
self.logger.error(f"{download_type} 加载弹窗在 {timeout} 秒后仍未消失")
|
||||
|
||||
# 检查是否还可以重试(retry_count=0 时执行重试,即第二次执行)
|
||||
if retry_count < 1:
|
||||
self.logger.warning(f"检测到超时,准备进行第 {retry_count + 2} 次尝试(重启应用)...")
|
||||
|
||||
# 执行重启逻辑
|
||||
from globals.driver_utils import launch_app_manually
|
||||
from page_objects.login_page import LoginPage
|
||||
|
||||
launch_app_manually(self.driver, self.device_id, "com.bjjw.cjgc", ".activity.LoginActivity")
|
||||
login_page = LoginPage(self.driver, self.wait)
|
||||
if login_page.is_login_page():
|
||||
login_page.login()
|
||||
|
||||
# 重新导航到下载页面
|
||||
more_download_btn = self.wait.until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, "com.bjjw.cjgc:id/img_5_layout"))
|
||||
)
|
||||
more_download_btn.click()
|
||||
|
||||
# 递归调用:增加 retry_count
|
||||
return self.more_download_page_manager_2(download_type, retry_count = retry_count + 1)
|
||||
else:
|
||||
self.logger.error(f"{download_type} 已达到最大重试次数,操作失败")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"检查加载弹窗时发生异常: {str(e)}")
|
||||
return False
|
||||
|
||||
def more_download_page_manager_2(self, download_type, retry_count=0):
|
||||
"""
|
||||
修改后的 manager_2,透传 retry_count 参数
|
||||
"""
|
||||
try:
|
||||
if not self.is_on_more_download_page():
|
||||
return False
|
||||
|
||||
self.click_download_button()
|
||||
|
||||
if download_type in ["原始数据", "历史数据"]:
|
||||
self.click_download_original_data()
|
||||
return self.wait_for_loading_dialog(download_type="原始数据", retry_count=retry_count)
|
||||
|
||||
elif download_type == "成果数据":
|
||||
self.click_download_result_data()
|
||||
return self.wait_for_loading_dialog(download_type="成果数据", retry_count=retry_count)
|
||||
|
||||
return False
|
||||
except Exception as e:
|
||||
self.logger.error(f"manager_2 执行出错: {str(e)}")
|
||||
return False
|
||||
|
||||
def more_download_page_manager(self):
|
||||
"""执行更多下载页面管理操作"""
|
||||
try:
|
||||
self.logger.info("开始执行更多下载页面操作")
|
||||
|
||||
# 检查是否在更多下载页面
|
||||
if not self.is_on_more_download_page():
|
||||
self.logger.error("不在更多下载页面")
|
||||
return False
|
||||
|
||||
# 点击下载历史数据按钮
|
||||
if not self.click_download_button():
|
||||
self.logger.error("点击下载历史数据按钮失败")
|
||||
return False
|
||||
|
||||
# 等待下载历史数据页面加载完成
|
||||
# time.sleep(3)
|
||||
|
||||
# 点击下载原始数据按钮
|
||||
if not self.click_download_original_data():
|
||||
self.logger.error("点击下载原始数据按钮失败")
|
||||
return False
|
||||
|
||||
# 等待下载操作完成
|
||||
time.sleep(1)
|
||||
|
||||
# 使用wait_for_loading_dialog函数等待下载过程中的加载弹窗消失
|
||||
if not self.wait_for_loading_dialog(download_type="原始数据"):
|
||||
self.logger.warning("下载过程中的加载弹窗未在预期时间内消失,但操作已完成")
|
||||
|
||||
# 等待一段时间,确保原始数据下载完成
|
||||
time.sleep(1)
|
||||
|
||||
# 点击下载成果数据按钮
|
||||
if not self.click_download_result_data():
|
||||
self.logger.error("点击下载成果数据按钮失败")
|
||||
return False
|
||||
|
||||
# 使用wait_for_loading_dialog函数等待下载过程中的加载弹窗消失
|
||||
if not self.wait_for_loading_dialog(download_type="成果数据"):
|
||||
self.logger.warning("成果数据下载过程中的加载弹窗未在预期时间内消失,但操作已完成")
|
||||
|
||||
self.logger.info("更多下载页面操作执行完成")
|
||||
return True
|
||||
except Exception as e:
|
||||
self.logger.error(f"执行更多下载页面操作时出错: {str(e)}")
|
||||
return False
|
||||
1629
page_objects/screenshot_page.py
Normal file
1629
page_objects/screenshot_page.py
Normal file
File diff suppressed because it is too large
Load Diff
1886
page_objects/upload_config_page.py
Normal file
1886
page_objects/upload_config_page.py
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user