python-qlv-helper 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- python_qlv_helper-0.2.0.dist-info/METADATA +252 -0
- python_qlv_helper-0.2.0.dist-info/RECORD +32 -0
- python_qlv_helper-0.2.0.dist-info/WHEEL +5 -0
- python_qlv_helper-0.2.0.dist-info/licenses/LICENSE +201 -0
- python_qlv_helper-0.2.0.dist-info/top_level.txt +1 -0
- qlv_helper/__init__.py +11 -0
- qlv_helper/controller/__init__.py +11 -0
- qlv_helper/controller/domestic_activity_order.py +24 -0
- qlv_helper/controller/main_page.py +30 -0
- qlv_helper/controller/order_detail.py +35 -0
- qlv_helper/controller/order_table.py +145 -0
- qlv_helper/controller/user_login.py +119 -0
- qlv_helper/http/__init__.py +11 -0
- qlv_helper/http/main_page.py +41 -0
- qlv_helper/http/order_page.py +313 -0
- qlv_helper/http/order_table_page.py +323 -0
- qlv_helper/po/__init__.py +11 -0
- qlv_helper/po/base_po.py +40 -0
- qlv_helper/po/domestic_activity_order_page.py +129 -0
- qlv_helper/po/login_page.py +136 -0
- qlv_helper/po/main_page.py +71 -0
- qlv_helper/po/wechat_auth_page.py +68 -0
- qlv_helper/utils/__init__.py +11 -0
- qlv_helper/utils/browser_utils.py +25 -0
- qlv_helper/utils/datetime_utils.py +16 -0
- qlv_helper/utils/file_handle.py +33 -0
- qlv_helper/utils/html_utils.py +59 -0
- qlv_helper/utils/ocr_helper.py +83 -0
- qlv_helper/utils/po_utils.py +113 -0
- qlv_helper/utils/stealth_browser.py +100 -0
- qlv_helper/utils/type_utils.py +111 -0
- qlv_helper/utils/windows_utils.py +36 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
4
|
+
# ProjectName: qlv-helper
|
|
5
|
+
# FileName: type_utils.py
|
|
6
|
+
# Description: 数据类型工具模块
|
|
7
|
+
# Author: zhouhanlin
|
|
8
|
+
# CreateDate: 2025/12/01
|
|
9
|
+
# Copyright ©2011-2025. Hunan xxxxxxx Company limited. All rights reserved.
|
|
10
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
11
|
+
"""
|
|
12
|
+
import re
|
|
13
|
+
from collections import OrderedDict
|
|
14
|
+
from typing import Any, Optional, Dict
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_key_by_index(ordered_dict: OrderedDict, index: int) -> Optional[str]:
|
|
18
|
+
"""有序字段根据索引获取值"""
|
|
19
|
+
if index < 0 or index >= len(ordered_dict):
|
|
20
|
+
return None
|
|
21
|
+
return list(ordered_dict.keys())[index]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_value_by_index(ordered_dict: OrderedDict, index: int) -> Any:
|
|
25
|
+
"""有序字段根据索引获取值"""
|
|
26
|
+
if index < 0 or index >= len(ordered_dict):
|
|
27
|
+
return None
|
|
28
|
+
key = list(ordered_dict.keys())[index]
|
|
29
|
+
return ordered_dict[key]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def safe_convert_advanced(value, return_type='auto'):
|
|
33
|
+
"""
|
|
34
|
+
增强版安全转换
|
|
35
|
+
Args:
|
|
36
|
+
value: 要转换的值
|
|
37
|
+
return_type: 'auto'|'int'|'float' - 指定返回类型
|
|
38
|
+
"""
|
|
39
|
+
if value is None:
|
|
40
|
+
return None
|
|
41
|
+
|
|
42
|
+
# 如果已经是目标类型,直接返回
|
|
43
|
+
if return_type == 'int' and isinstance(value, int):
|
|
44
|
+
return value
|
|
45
|
+
elif return_type == 'float' and isinstance(value, float):
|
|
46
|
+
return value
|
|
47
|
+
elif return_type == 'auto' and isinstance(value, (int, float)):
|
|
48
|
+
return value
|
|
49
|
+
|
|
50
|
+
# 转换为字符串处理
|
|
51
|
+
str_value = str(value).strip()
|
|
52
|
+
|
|
53
|
+
if not str_value:
|
|
54
|
+
return value
|
|
55
|
+
|
|
56
|
+
# 处理百分比格式
|
|
57
|
+
if str_value.endswith('%'):
|
|
58
|
+
try:
|
|
59
|
+
num_value = float(str_value.rstrip('%')) / 100.0
|
|
60
|
+
if return_type == 'int':
|
|
61
|
+
return int(round(num_value))
|
|
62
|
+
elif return_type == 'float' or return_type == 'auto':
|
|
63
|
+
return num_value
|
|
64
|
+
except ValueError:
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
# 处理货币格式(如 ¥100.50, $1,000.00)
|
|
68
|
+
currency_pattern = r'^[^\d\-.]*([\-]?\d+(?:,\d{3})*(?:\.\d+)?)[^\d]*$'
|
|
69
|
+
match = re.match(currency_pattern, str_value)
|
|
70
|
+
if match:
|
|
71
|
+
try:
|
|
72
|
+
cleaned = match.group(1).replace(',', '')
|
|
73
|
+
num_value = float(cleaned)
|
|
74
|
+
|
|
75
|
+
if return_type == 'int':
|
|
76
|
+
return int(round(num_value))
|
|
77
|
+
elif return_type == 'float':
|
|
78
|
+
return num_value
|
|
79
|
+
elif return_type == 'auto':
|
|
80
|
+
# 如果是整数,返回int,否则返回float
|
|
81
|
+
return int(num_value) if num_value.is_integer() else num_value
|
|
82
|
+
except ValueError:
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
# 常规数字转换
|
|
86
|
+
try:
|
|
87
|
+
# 移除空格和特殊字符(保留数字、小数点、负号)
|
|
88
|
+
cleaned = re.sub(r'[^\d\.\-]', '', str_value)
|
|
89
|
+
if cleaned and cleaned != '-':
|
|
90
|
+
num_value = float(cleaned)
|
|
91
|
+
|
|
92
|
+
if return_type == 'int':
|
|
93
|
+
return int(round(num_value))
|
|
94
|
+
elif return_type == 'float':
|
|
95
|
+
return num_value
|
|
96
|
+
elif return_type == 'auto':
|
|
97
|
+
return int(num_value) if num_value.is_integer() else num_value
|
|
98
|
+
except ValueError:
|
|
99
|
+
pass
|
|
100
|
+
|
|
101
|
+
# 所有转换都失败,返回原值
|
|
102
|
+
return value
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def convert_cn_to_en(data: Dict[str, Any], header_map: OrderedDict[str, str]) -> Dict[str, Any]:
|
|
106
|
+
"""把中文键转成英文键"""
|
|
107
|
+
# 1. 构建中文 → 英文映射
|
|
108
|
+
cn_to_en = {cn: en for en, cn in header_map.items()}
|
|
109
|
+
|
|
110
|
+
# 2. 转换
|
|
111
|
+
return {cn_to_en.get(k, k): v for k, v in data.items()}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
4
|
+
# ProjectName: qlv-helper
|
|
5
|
+
# FileName: windows_utils.py
|
|
6
|
+
# Description: windows窗口的操作工具模块
|
|
7
|
+
# Author: ASUS
|
|
8
|
+
# CreateDate: 2025/11/27
|
|
9
|
+
# Copyright ©2011-2025. Hunan xxxxxxx Company limited. All rights reserved.
|
|
10
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
11
|
+
"""
|
|
12
|
+
import os
|
|
13
|
+
import base64
|
|
14
|
+
from airtest.cli.parser import cli_setup
|
|
15
|
+
from airtest.core.api import touch, auto_setup, Template
|
|
16
|
+
|
|
17
|
+
allow_btn_base64_str = 'iVBORw0KGgoAAAANSUhEUgAAATYAAABACAIAAAAf0syWAAAACXBIWXMAAB2HAAAdhwGP5fFlAAAEKElEQVR42u2dv08UQRSAr1MSKxMLCv4DS7W6ilha+gdILAxcQi0kWFyBwVhR2EJCBZUJNhIblCPEXC6n2LheLjl/hEsMxAvkUODAl0wclp3Zmb1f3CZ+L18j7E7x1i9vZvfNkDkjCCLFkSEFBIGiBEH0WtGtRmUiWBgtzw4XclfWHwBAnxDFRLRcsCjSJVL0sHU0VV0eWh8jdwCXiUg3XV05Oj1xKfphv3bz/WOSBTAobhVnRMNYRUVicgQwWERDu6Kbv4KrzG8BBo1oqAvpBUVlwUp2ANKAyGhRNFvKkxqANHC3/NSi6I2NcVIDkAZGNictipIXgPSAogAoCgAoCoCiAICiAICiACgKACgKgKKQBrKl/FxttR/D3v80T3pRFLolaO7Ioynv19q9cfzzwtredtxv5VedDQsoCue8/FlUj2apvtHWjVPVZXVjoRFYL9g9PuhgWEBROOfFjzduzdzIXXF6a4GZ66IodIhMU5utP/JQZKJrvSCJXdpSsd38ObNcFIVu/fz2e9e6iVetJCPiWd8JyQjq4Url1D9s65BIfSOgKFzwKs5PR3m0jia2h6fKen2LoigKffFTUf53to2UXO+YEWPlLhHV/N+AjSgKLmR5qfwUi7yH1GiZ5WKvpZESao6PoigKbaw/E75obdfSuBKKoigKnuIZXh+u7W3LP8PInDZo7oRRXzXDES6MqtvBXE8u1TfiSjSKoii4FO3J3+fRy9c4RdW3Vmu7AoqiKPi7/MQxXSfVZxU1KRVEHkGVQbPlQDc5yAhqzqyu1y0KXvdQFEXBU0jNdaP5ULRycZ9hzG8wKIqi0BesNjoUVcXT7Z45AU4Y5uslQFEUbVtRb3lEURSFHu9xiTTodqkoE10UhZ6hmocie1xQFEXJS1pQPQaRDyQoiqLkJRXM1VatH1fcispd5pth0z3vWyVAUfCg2vrMnaJuRa0buCPuyRJX6jOKoih0ju5PMIXpRtFsKa/f6JqFFEVRFBKh+4SsRyIkUTSimf5qoha3cecVoSiKgh/d9Ld7fGDdjOZQVAqjWSEjByzIsHEbYlAURcFTPPXmFYdIuuFeZA47LNerSWxknalrsirLjj2oKIqi4JdTvSJyb+Z2dwhFDs7VF3sP40RRFAU7epu1iOo9iEhdX2gE+tAwvVlUbDRvV3u+kwyLoigKrnbcJBb1u99Q4FhdFAUAFAVAUQBAUQAURVEAFAUAFAX4DxQd2ZwkLwBpQGS0KHrv43NSA5AGREaLotPVFVIDkAZERouiX5r1a28fkh2AwXL93aNKs25RVOLZ11ckCGCwzH9/rZWMKnpy2rpTfEKOAAbF7eKMaBirqMRh60jmwUPrYyQL4DIR6aaqyyJg2MdM3ObgrUYlFyyOlmeHCzlyB9A/RDERbSJYEOlMEzNnBEGkOP4C+x6pJBF8uPMAAAAASUVORK5CYII='
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def gen_allow_btn_image(image_name: str) -> None:
|
|
21
|
+
# 1. 解码 Base64 成二进制数据
|
|
22
|
+
image_data = base64.b64decode(allow_btn_base64_str)
|
|
23
|
+
|
|
24
|
+
# 2. 写入文件(保存图片)
|
|
25
|
+
with open(image_name, "wb") as image_file:
|
|
26
|
+
image_file.write(image_data)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def windows_on_click(image_name: str, windows_title: str, is_delete: bool = True) -> None:
|
|
30
|
+
if not cli_setup():
|
|
31
|
+
auto_setup(__file__, logdir=False, devices=[f"Windows:///?title_re=^{windows_title}$"])
|
|
32
|
+
|
|
33
|
+
touch(Template(filename=image_name, record_pos=(0, 0), resolution=(1920, 1080)))
|
|
34
|
+
if is_delete is True:
|
|
35
|
+
if os.path.exists(image_name):
|
|
36
|
+
os.remove(image_name)
|