diff --git a/globals/__pycache__/apis.cpython-312.pyc b/globals/__pycache__/apis.cpython-312.pyc index d20ad2a..ad1efca 100644 Binary files a/globals/__pycache__/apis.cpython-312.pyc and b/globals/__pycache__/apis.cpython-312.pyc differ diff --git a/globals/apis.py b/globals/apis.py index 3fc3b9b..57700b3 100644 --- a/globals/apis.py +++ b/globals/apis.py @@ -1,6 +1,7 @@ import requests import json import logging +import time import socket from typing import Optional, Dict, Any import globals.global_variable as global_variable @@ -52,58 +53,6 @@ def send_tcp_command(command="StartMultiple", host="127.0.0.1", port=8888, timeo logging.info(f"发送命令时发生错误: {str(e)}") return None -def get_breakpoint_list(): - """ - 获取需要处理的断点列表 - """ - # 请求参数 - params = { - 'user_name': global_variable.get_username() - } - - # 请求地址 - url = "https://engineering.yuxindazhineng.com/index/index/get_name_all" - - try: - # 发送GET请求 - response = requests.get(url, params=params, timeout=30) - - # 检查请求是否成功 - if response.status_code == 200: - result = response.json() - - # 检查接口返回状态 - if result.get('code') == 0: - data = result.get('data', []) - logging.info("成功获取断点列表,数据条数:", len(data)) - - # 打印断点信息 - # for item in data: - # logging.info(f"线路编码: {item.get('line_num')}, " - # f"线路名称: {item.get('line_name')}, " - # f"状态: {item.get('status')}, " - # f"用户: {item.get('name')}") - - return data - else: - logging.info(f"接口返回错误: {result.get('code')}") - return [{"id": 37, - "user_name": "wangshun", - "name": "wangshun", - "line_num": "L193588", - "line_name": "CDWZQ-2标-155号路基左线-461221-461570-155左-平原", - "status": 3 - }] - else: - logging.info(f"请求失败,状态码: {response.status_code}") - return [] - - except requests.exceptions.RequestException as e: - logging.info(f"请求异常: {e}") - return [] - except ValueError as e: - logging.info(f"JSON解析错误: {e}") - return [] def get_measurement_task(): """ @@ -388,96 +337,139 @@ def get_line_info_and_save_global(user_name: str) -> bool: api_url = "https://engineering.yuxindazhineng.com/index/index/get_name_all" request_params = {"user_name": user_name} # GET请求参数 timeout = 10 # 请求超时时间(秒),避免卡进程 + max_retries = 3 # 最大重试次数 + retry_interval = 2 # 重试间隔(秒) - try: - # 1. 发送GET请求 - response = requests.get( - url=api_url, - params=request_params, # GET参数用params传递,自动拼接到URL后,规范且防乱码 - timeout=timeout, - verify=False # 禁用SSL验证,适配HTTPS接口 - ) - - # 2. 校验HTTP状态码(先确保请求本身成功) - if response.status_code != 200: - logging.error(f"接口请求失败,HTTP状态码异常:{response.status_code},响应内容:{response.text}") - return False - - # 3. 解析JSON响应(接口返回是JSON格式,需解析为字典) + for retry in range(max_retries): try: - response_data = response.json() - except Exception as e: - logging.error(f"接口返回内容非合法JSON,无法解析:{response.text},错误:{str(e)}") - return False + # 1. 发送GET请求 + response = requests.get( + url=api_url, + params=request_params, # GET参数用params传递,自动拼接到URL后,规范且防乱码 + timeout=timeout, + verify=False # 禁用SSL验证,适配HTTPS接口 + ) - # 4. 校验业务状态码(接口约定:code=0成功,-1失败) - business_code = response_data.get("code") - if business_code == 0: - logging.info("接口业务请求成功,开始解析数据") - elif business_code == -1: - logging.error(f"接口业务请求失败,业务状态码code=-1,返回数据:{response_data}") - return False - else: - logging.warning(f"接口返回未知业务状态码:{business_code},请确认接口文档") - return False + # 2. 校验HTTP状态码(先确保请求本身成功) + if response.status_code != 200: + logging.error(f"接口请求失败,HTTP状态码异常:{response.status_code},响应内容:{response.text}") + if retry < max_retries - 1: + logging.info(f"将在{retry_interval}秒后进行第{retry+2}次重试") + time.sleep(retry_interval) + continue + return False - # 5. 提取data字段,校验数据是否存在 - api_data_list = response_data.get("data") - if not api_data_list: - logging.warning("接口业务成功,但data字段为空或无数据") - return False + # 3. 解析JSON响应(接口返回是JSON格式,需解析为字典) + try: + response_data = response.json() + except Exception as e: + logging.error(f"接口返回内容非合法JSON,无法解析:{response.text},错误:{str(e)}") + if retry < max_retries - 1: + logging.info(f"将在{retry_interval}秒后进行第{retry+2}次重试") + time.sleep(retry_interval) + continue + return False - # 6. 校验data是否为列表类型 - if not isinstance(api_data_list, list): - logging.error(f"data字段不是列表类型,实际类型:{type(api_data_list)},内容:{api_data_list}") - return False + # 4. 校验业务状态码(接口约定:code=0成功,-1失败) + business_code = response_data.get("code") + if business_code == 0: + logging.info("接口业务请求成功,开始解析数据") + elif business_code == -1: + logging.error(f"接口业务请求失败,业务状态码code=-1,返回数据:{response_data}") + if retry < max_retries - 1: + logging.info(f"将在{retry_interval}秒后进行第{retry+2}次重试") + time.sleep(retry_interval) + continue + return False + else: + logging.warning(f"接口返回未知业务状态码:{business_code},请确认接口文档") + if retry < max_retries - 1: + logging.info(f"将在{retry_interval}秒后进行第{retry+2}次重试") + time.sleep(retry_interval) + continue + return False - found_valid_data = False - - # 7. 遍历列表,提取所有status=3的数据 - for item in api_data_list: - # 确保每个item是字典 - if not isinstance(item, dict): - logging.warning(f"列表中的元素不是字典类型,跳过:{item}") + # 5. 提取data字段,校验数据是否存在 + api_data_list = response_data.get("data") + if not api_data_list: + logging.warning("接口业务成功,但data字段为空或无数据") + if retry < max_retries - 1: + logging.info(f"将在{retry_interval}秒后进行第{retry+2}次重试") + time.sleep(retry_interval) + continue + return False + + # 6. 校验data是否为列表类型 + if not isinstance(api_data_list, list): + logging.error(f"data字段不是列表类型,实际类型:{type(api_data_list)},内容:{api_data_list}") + if retry < max_retries - 1: + logging.info(f"将在{retry_interval}秒后进行第{retry+2}次重试") + time.sleep(retry_interval) + continue + return False + + found_valid_data = False + + # 7. 遍历列表,提取所有status=3的数据 + for item in api_data_list: + # 确保每个item是字典 + if not isinstance(item, dict): + logging.warning(f"列表中的元素不是字典类型,跳过:{item}") + continue + + # 获取字段值 + data_status = item.get("status") + line_num = item.get("line_num") + line_name = item.get("line_name") + + # 校验status是否为3,且目标字段非空 + if data_status == 3 and line_num and line_name: + # # 存入全局字典:key=line_num,value=line_name + # global_variable.GLOBAL_UPLOAD_BREAKPOINT_DICT[line_num] = line_name + # 存入全局字典:key=line_name,value=line_num + global_variable.get_upload_breakpoint_dict()[line_name] = line_num + + print(f"当前全局字典数据上传线路字典数据:{global_variable.get_upload_breakpoint_dict()}") + # 如果line_name不在列表中,则添加 + if line_name not in global_variable.get_upload_breakpoint_list(): + global_variable.get_upload_breakpoint_list().append(line_name) + + logging.info(f"找到status=3的线路信息:line_num={line_num}, line_name={line_name}") + found_valid_data = True + + if found_valid_data: + logging.info(f"成功提取所有status=3的线路信息,当前全局字典数据:{global_variable.get_upload_breakpoint_dict()}") + return True + else: + logging.warning("data列表中未找到任何status=3且字段完整的线路信息") + if retry < max_retries - 1: + logging.info(f"将在{retry_interval}秒后进行第{retry+2}次重试") + time.sleep(retry_interval) + continue + return False + + # 捕获所有请求相关异常(超时、连接失败、网络异常等) + except requests.exceptions.Timeout: + logging.error(f"调用get_name_all接口超时,超时时间:{timeout}秒,请求参数:{request_params}") + if retry < max_retries - 1: + logging.info(f"将在{retry_interval}秒后进行第{retry+2}次重试") + time.sleep(retry_interval) + continue + return False + except requests.exceptions.ConnectionError: + logging.error(f"调用get_name_all接口连接失败,检查网络或接口地址是否正确:{api_url}") + if retry < max_retries - 1: + logging.info(f"将在{retry_interval}秒后进行第{retry+2}次重试") + time.sleep(retry_interval) + continue + return False + except Exception as e: + logging.error(f"调用get_name_all接口时发生未知异常:{str(e)}", exc_info=True) # exc_info=True打印异常堆栈,方便排查 + if retry < max_retries - 1: + logging.info(f"将在{retry_interval}秒后进行第{retry+2}次重试") + time.sleep(retry_interval) continue - - # 获取字段值 - data_status = item.get("status") - line_num = item.get("line_num") - line_name = item.get("line_name") - - # 校验status是否为3,且目标字段非空 - if data_status == 3 and line_num and line_name: - # # 存入全局字典:key=line_num,value=line_name - # global_variable.GLOBAL_UPLOAD_BREAKPOINT_DICT[line_num] = line_name - # 存入全局字典:key=line_name,value=line_num - global_variable.get_upload_breakpoint_dict()[line_name] = line_num - - print(f"当前全局字典数据上传线路字典数据:{global_variable.get_upload_breakpoint_dict()}") - # 如果line_name不在列表中,则添加 - if line_name not in global_variable.get_upload_breakpoint_list(): - global_variable.get_upload_breakpoint_list().append(line_name) - - logging.info(f"找到status=3的线路信息:line_num={line_num}, line_name={line_name}") - found_valid_data = True - - if found_valid_data: - logging.info(f"成功提取所有status=3的线路信息,当前全局字典数据:{global_variable.get_upload_breakpoint_dict()}") - return True - else: - logging.warning("data列表中未找到任何status=3且字段完整的线路信息") return False - - # 捕获所有请求相关异常(超时、连接失败、网络异常等) - except requests.exceptions.Timeout: - logging.error(f"调用get_name_all接口超时,超时时间:{timeout}秒,请求参数:{request_params}") - return False - except requests.exceptions.ConnectionError: - logging.error(f"调用get_name_all接口连接失败,检查网络或接口地址是否正确:{api_url}") - return False - except Exception as e: - logging.error(f"调用get_name_all接口时发生未知异常:{str(e)}", exc_info=True) # exc_info=True打印异常堆栈,方便排查 - return False def get_accounts_from_server(yh_id): """从服务器获取账户信息""" diff --git a/page_objects/__pycache__/screenshot_page.cpython-312.pyc b/page_objects/__pycache__/screenshot_page.cpython-312.pyc index be486cb..254efe3 100644 Binary files a/page_objects/__pycache__/screenshot_page.cpython-312.pyc and b/page_objects/__pycache__/screenshot_page.cpython-312.pyc differ diff --git a/page_objects/__pycache__/upload_config_page.cpython-312.pyc b/page_objects/__pycache__/upload_config_page.cpython-312.pyc index 9ab255e..1b5ea0c 100644 Binary files a/page_objects/__pycache__/upload_config_page.cpython-312.pyc and b/page_objects/__pycache__/upload_config_page.cpython-312.pyc differ diff --git a/page_objects/upload_config_page.py b/page_objects/upload_config_page.py index d645bc3..fb1906f 100644 --- a/page_objects/upload_config_page.py +++ b/page_objects/upload_config_page.py @@ -1666,7 +1666,7 @@ class UploadConfigPage: minor_conditions_list = [] # 次要工况列表 [{point_id, work_type, workinfoname}] # 定义阈值:出现次数少于这个值的认为是次要工况 - minor_threshold = 3 # 可以根据实际情况调整 + minor_threshold = 2 # 可以根据实际情况调整 for work_type, workinfoname_counts in work_type_stats.items(): if workinfoname_counts: @@ -1862,13 +1862,14 @@ class UploadConfigPage: return False - # # 表达填写完成,点击"保存上传"并处理弹窗 - # if not self.click_save_upload_and_handle_dialogs(): - # self.logger.error("点击保存上传并处理弹窗失败") - # return False + # 表达填写完成,点击"保存上传"并处理弹窗 + if not self.click_save_upload_and_handle_dialogs(): + self.logger.error("点击保存上传并处理弹窗失败") + return False - # 暂不上传,使用返回按钮替代。 - self.driver.back() + # # 暂不上传,使用返回按钮替代。 + # self.driver.back() + # return True # 等待上传,查看loading弹窗。没有就下一个 diff --git a/scheduler.py b/scheduler.py index a2b35cb..243acd5 100644 --- a/scheduler.py +++ b/scheduler.py @@ -29,15 +29,7 @@ def update_file_status(username, from_status, to_status): try: with open(TIME_FILE_PATH, 'r', encoding='utf-8') as f: lines = f.readlines() - - # new_lines = [] - # for line in lines: - # clean_line = line.strip() - # # 匹配逻辑:包含用户名 且 以 from_status 结尾 - # if f" {username} " in line and clean_line.endswith(from_status): - # line = line.replace(from_status, to_status) - # success = True - # new_lines.append(line) + new_lines = [] for line in lines: # 使用正则确保精准匹配用户名和结尾状态 @@ -73,7 +65,7 @@ def parse_time_config(): for line in f: line = line.strip() # 匹配:用户名 时间 true (仅获取待处理任务) - match = re.search(r'(\w+)\s+(\d{1,2}:\d{2}:\d{2})\s+ok$', line) + match = re.search(r'(\w+)\s+(\d{4}-\d{1,2}-\d{1,2}\s+\d{1,2}:\d{2}:\d{2})\s+ok$', line) if match: username, scheduled_time = match.group(1), match.group(2) time_map[username] = scheduled_time @@ -81,6 +73,39 @@ def parse_time_config(): print(f"❌ 解析 time.txt 失败: {e}") return time_map + + +def normalize_datetime(time_str): + """ + 将时间字符串格式化为标准格式:YYYY-MM-DD HH:MM:SS + 补全单数字的月、日、时 + 例如:2024-1-15 9:52:20 -> 2024-01-15 09:52:20 + """ + try: + # 分割日期和时间部分 + if ' ' in time_str: + date_part, time_part = time_str.split(' ', 1) + + # 补全日期部分的单数字 + date_parts = date_part.split('-') + if len(date_parts) == 3: + year = date_parts[0] + month = date_parts[1].zfill(2) # 月补零 + day = date_parts[2].zfill(2) # 日补零 + date_part = f"{year}-{month}-{day}" + + # 补全时间部分的单数字小时 + time_parts = time_part.split(':') + if len(time_parts) >= 1: + hour = time_parts[0].zfill(2) # 小时补零 + time_part = f"{hour}:{':'.join(time_parts[1:])}" + + return f"{date_part} {time_part}" + return time_str + except Exception as e: + print(f"⚠️ 时间格式标准化失败 ({time_str}): {e}") + return time_str + def get_combined_tasks(): """ 结合接口(is_ok==1)和本地文件(ok)筛选任务 @@ -96,10 +121,10 @@ def get_combined_tasks(): return {} task_list = {} - today = datetime.now().strftime("%Y-%m-%d") + # today = datetime.now().strftime("%Y-%m-%d") for account in accounts: - if account.get('is_ok') == 1 or account.get('username') == "CZSCZQ13A1xuliguo": + if account.get('is_ok') == 1: user = account.get('username') ip = account.get('device_ip') port = account.get('device_port') @@ -111,12 +136,13 @@ def get_combined_tasks(): # 确保时间是两位数格式 raw_time = local_times[user] # 将时间格式化为两位数:9:52:20 -> 09:52:20 - if ':' in raw_time: - parts = raw_time.split(':') - if len(parts[0]) == 1: - raw_time = f"0{raw_time}" # 补齐前导零 + # if ':' in raw_time: + # parts = raw_time.split(':') + # if len(parts[0]) == 1: + # raw_time = f"0{raw_time}" # 补齐前导零 - full_time = f"{today} {raw_time}" + # full_time = f"{today} {raw_time}" + full_time = normalize_datetime(raw_time) task_list[address] = {"time": full_time, "user": user} return task_list diff --git a/test_results/上传失败的断点.txt b/test_results/上传失败的断点.txt index f71ccdf..7dcde69 100644 --- a/test_results/上传失败的断点.txt +++ b/test_results/上传失败的断点.txt @@ -1,3 +1,4 @@ -CZSCZQ-13A-二工区-沙马大桥-7#墩-山区 +CZSCZQ-13A-二工区-沙马大桥-6#墩-山区 CZSCZQ-13A-二工区-沙马大桥-2#墩身-山区 CZSCZQ-13A-二工区-沙马大桥-1#墩身-山区 +CZSCZQ-13A-二工区-沙马大桥-7#墩-山区