Compare commits
4 Commits
4e49793416
...
9f23776d5a
| Author | SHA1 | Date | |
|---|---|---|---|
| 9f23776d5a | |||
| d83ca7557e | |||
| 119bb845b4 | |||
| 6274c83dd5 |
Binary file not shown.
2043
build/沉降观测自动截图/Analysis-00.toc
Normal file
2043
build/沉降观测自动截图/Analysis-00.toc
Normal file
File diff suppressed because it is too large
Load Diff
293
build/沉降观测自动截图/EXE-00.toc
Normal file
293
build/沉降观测自动截图/EXE-00.toc
Normal file
@@ -0,0 +1,293 @@
|
|||||||
|
('D:\\Projects\\cjgc_screenshot\\dist\\沉降观测自动截图.exe',
|
||||||
|
True,
|
||||||
|
False,
|
||||||
|
False,
|
||||||
|
'C:\\Program '
|
||||||
|
'Files\\Python312\\Lib\\site-packages\\PyInstaller\\bootloader\\images\\icon-console.ico',
|
||||||
|
None,
|
||||||
|
False,
|
||||||
|
False,
|
||||||
|
b'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<assembly xmlns='
|
||||||
|
b'"urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">\n <trustInfo x'
|
||||||
|
b'mlns="urn:schemas-microsoft-com:asm.v3">\n <security>\n <requested'
|
||||||
|
b'Privileges>\n <requestedExecutionLevel level="asInvoker" uiAccess='
|
||||||
|
b'"false"/>\n </requestedPrivileges>\n </security>\n </trustInfo>\n '
|
||||||
|
b'<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">\n <'
|
||||||
|
b'application>\n <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f'
|
||||||
|
b'0}"/>\n <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>\n '
|
||||||
|
b' <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>\n <s'
|
||||||
|
b'upportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>\n <supporte'
|
||||||
|
b'dOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>\n </application>\n <'
|
||||||
|
b'/compatibility>\n <application xmlns="urn:schemas-microsoft-com:asm.v3">'
|
||||||
|
b'\n <windowsSettings>\n <longPathAware xmlns="http://schemas.micros'
|
||||||
|
b'oft.com/SMI/2016/WindowsSettings">true</longPathAware>\n </windowsSett'
|
||||||
|
b'ings>\n </application>\n <dependency>\n <dependentAssembly>\n <ass'
|
||||||
|
b'emblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version='
|
||||||
|
b'"6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" langua'
|
||||||
|
b'ge="*"/>\n </dependentAssembly>\n </dependency>\n</assembly>',
|
||||||
|
True,
|
||||||
|
False,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
'D:\\Projects\\cjgc_screenshot\\build\\沉降观测自动截图\\沉降观测自动截图.pkg',
|
||||||
|
[('pyi-contents-directory _internal', '', 'OPTION'),
|
||||||
|
('PYZ-00.pyz',
|
||||||
|
'D:\\Projects\\cjgc_screenshot\\build\\沉降观测自动截图\\PYZ-00.pyz',
|
||||||
|
'PYZ'),
|
||||||
|
('struct',
|
||||||
|
'D:\\Projects\\cjgc_screenshot\\build\\沉降观测自动截图\\localpycs\\struct.pyc',
|
||||||
|
'PYMODULE'),
|
||||||
|
('pyimod01_archive',
|
||||||
|
'D:\\Projects\\cjgc_screenshot\\build\\沉降观测自动截图\\localpycs\\pyimod01_archive.pyc',
|
||||||
|
'PYMODULE'),
|
||||||
|
('pyimod02_importers',
|
||||||
|
'D:\\Projects\\cjgc_screenshot\\build\\沉降观测自动截图\\localpycs\\pyimod02_importers.pyc',
|
||||||
|
'PYMODULE'),
|
||||||
|
('pyimod03_ctypes',
|
||||||
|
'D:\\Projects\\cjgc_screenshot\\build\\沉降观测自动截图\\localpycs\\pyimod03_ctypes.pyc',
|
||||||
|
'PYMODULE'),
|
||||||
|
('pyimod04_pywin32',
|
||||||
|
'D:\\Projects\\cjgc_screenshot\\build\\沉降观测自动截图\\localpycs\\pyimod04_pywin32.pyc',
|
||||||
|
'PYMODULE'),
|
||||||
|
('pyiboot01_bootstrap',
|
||||||
|
'C:\\Program '
|
||||||
|
'Files\\Python312\\Lib\\site-packages\\PyInstaller\\loader\\pyiboot01_bootstrap.py',
|
||||||
|
'PYSOURCE'),
|
||||||
|
('pyi_rth_inspect',
|
||||||
|
'C:\\Program '
|
||||||
|
'Files\\Python312\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_inspect.py',
|
||||||
|
'PYSOURCE'),
|
||||||
|
('pyi_rth_pkgutil',
|
||||||
|
'C:\\Program '
|
||||||
|
'Files\\Python312\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pkgutil.py',
|
||||||
|
'PYSOURCE'),
|
||||||
|
('pyi_rth_multiprocessing',
|
||||||
|
'C:\\Program '
|
||||||
|
'Files\\Python312\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_multiprocessing.py',
|
||||||
|
'PYSOURCE'),
|
||||||
|
('scheduler', 'D:\\Projects\\cjgc_screenshot\\scheduler.py', 'PYSOURCE'),
|
||||||
|
('selenium\\webdriver\\common\\windows\\selenium-manager.exe',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\common\\windows\\selenium-manager.exe',
|
||||||
|
'BINARY'),
|
||||||
|
('python312.dll', 'C:\\Program Files\\Python312\\python312.dll', 'BINARY'),
|
||||||
|
('select.pyd', 'C:\\Program Files\\Python312\\DLLs\\select.pyd', 'EXTENSION'),
|
||||||
|
('_multiprocessing.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\_multiprocessing.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('pyexpat.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\pyexpat.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('_ssl.pyd', 'C:\\Program Files\\Python312\\DLLs\\_ssl.pyd', 'EXTENSION'),
|
||||||
|
('_hashlib.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\_hashlib.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('unicodedata.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\unicodedata.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('_decimal.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\_decimal.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('_socket.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\_socket.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('_lzma.pyd', 'C:\\Program Files\\Python312\\DLLs\\_lzma.pyd', 'EXTENSION'),
|
||||||
|
('_bz2.pyd', 'C:\\Program Files\\Python312\\DLLs\\_bz2.pyd', 'EXTENSION'),
|
||||||
|
('_ctypes.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\_ctypes.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('_queue.pyd', 'C:\\Program Files\\Python312\\DLLs\\_queue.pyd', 'EXTENSION'),
|
||||||
|
('_overlapped.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\_overlapped.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('_asyncio.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\_asyncio.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('charset_normalizer\\md__mypyc.cp312-win_amd64.pyd',
|
||||||
|
'C:\\Program '
|
||||||
|
'Files\\Python312\\Lib\\site-packages\\charset_normalizer\\md__mypyc.cp312-win_amd64.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('charset_normalizer\\md.cp312-win_amd64.pyd',
|
||||||
|
'C:\\Program '
|
||||||
|
'Files\\Python312\\Lib\\site-packages\\charset_normalizer\\md.cp312-win_amd64.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('_uuid.pyd', 'C:\\Program Files\\Python312\\DLLs\\_uuid.pyd', 'EXTENSION'),
|
||||||
|
('_wmi.pyd', 'C:\\Program Files\\Python312\\DLLs\\_wmi.pyd', 'EXTENSION'),
|
||||||
|
('api-ms-win-core-synch-l1-2-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-synch-l1-2-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-filesystem-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-filesystem-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-conio-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-conio-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('VCRUNTIME140.dll',
|
||||||
|
'C:\\Program Files\\Python312\\VCRUNTIME140.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-locale-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-locale-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-math-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-math-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-convert-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-convert-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-time-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-time-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-string-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-string-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-stdio-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-stdio-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-runtime-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-runtime-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-environment-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-environment-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-process-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-process-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-heap-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-heap-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-utility-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-utility-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('libcrypto-3.dll',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\libcrypto-3.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('libssl-3.dll',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\libssl-3.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('libffi-8.dll',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\libffi-8.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('ucrtbase.dll', 'D:\\Resource\\JDK\\JavaJDK17\\bin\\ucrtbase.dll', 'BINARY'),
|
||||||
|
('api-ms-win-core-debug-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-debug-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-profile-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-profile-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-errorhandling-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-errorhandling-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-console-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-console-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-synch-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-synch-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-heap-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-heap-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-file-l2-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-file-l2-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-interlocked-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-interlocked-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-memory-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-memory-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-processenvironment-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-processenvironment-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-processthreads-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-processthreads-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-file-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-file-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-file-l1-2-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-file-l1-2-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-localization-l1-2-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-localization-l1-2-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-processthreads-l1-1-1.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-processthreads-l1-1-1.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-namedpipe-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-namedpipe-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-string-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-string-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-sysinfo-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-sysinfo-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-datetime-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-datetime-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-rtlsupport-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-rtlsupport-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-util-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-util-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-timezone-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-timezone-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-handle-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-handle-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-libraryloader-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-libraryloader-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('certifi\\py.typed',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\certifi\\py.typed',
|
||||||
|
'DATA'),
|
||||||
|
('certifi\\cacert.pem',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\certifi\\cacert.pem',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\common\\mutation-listener.js',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\common\\mutation-listener.js',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\remote\\getAttribute.js',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\remote\\getAttribute.js',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\firefox\\webdriver_prefs.json',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\firefox\\webdriver_prefs.json',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\common\\devtools\\v137\\py.typed',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\common\\devtools\\v137\\py.typed',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\common\\devtools\\v138\\py.typed',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\common\\devtools\\v138\\py.typed',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\common\\linux\\selenium-manager',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\common\\linux\\selenium-manager',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\remote\\findElements.js',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\remote\\findElements.js',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\remote\\isDisplayed.js',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\remote\\isDisplayed.js',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\common\\devtools\\v139\\py.typed',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\common\\devtools\\v139\\py.typed',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\common\\macos\\selenium-manager',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\common\\macos\\selenium-manager',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\py.typed',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\py.typed',
|
||||||
|
'DATA'),
|
||||||
|
('base_library.zip',
|
||||||
|
'D:\\Projects\\cjgc_screenshot\\build\\沉降观测自动截图\\base_library.zip',
|
||||||
|
'DATA')],
|
||||||
|
[],
|
||||||
|
False,
|
||||||
|
False,
|
||||||
|
1770717074,
|
||||||
|
[('run.exe',
|
||||||
|
'C:\\Program '
|
||||||
|
'Files\\Python312\\Lib\\site-packages\\PyInstaller\\bootloader\\Windows-64bit-intel\\run.exe',
|
||||||
|
'EXECUTABLE')],
|
||||||
|
'C:\\Program Files\\Python312\\python312.dll')
|
||||||
269
build/沉降观测自动截图/PKG-00.toc
Normal file
269
build/沉降观测自动截图/PKG-00.toc
Normal file
@@ -0,0 +1,269 @@
|
|||||||
|
('D:\\Projects\\cjgc_screenshot\\build\\沉降观测自动截图\\沉降观测自动截图.pkg',
|
||||||
|
{'BINARY': True,
|
||||||
|
'DATA': True,
|
||||||
|
'EXECUTABLE': True,
|
||||||
|
'EXTENSION': True,
|
||||||
|
'PYMODULE': True,
|
||||||
|
'PYSOURCE': True,
|
||||||
|
'PYZ': False,
|
||||||
|
'SPLASH': True,
|
||||||
|
'SYMLINK': False},
|
||||||
|
[('pyi-contents-directory _internal', '', 'OPTION'),
|
||||||
|
('PYZ-00.pyz',
|
||||||
|
'D:\\Projects\\cjgc_screenshot\\build\\沉降观测自动截图\\PYZ-00.pyz',
|
||||||
|
'PYZ'),
|
||||||
|
('struct',
|
||||||
|
'D:\\Projects\\cjgc_screenshot\\build\\沉降观测自动截图\\localpycs\\struct.pyc',
|
||||||
|
'PYMODULE'),
|
||||||
|
('pyimod01_archive',
|
||||||
|
'D:\\Projects\\cjgc_screenshot\\build\\沉降观测自动截图\\localpycs\\pyimod01_archive.pyc',
|
||||||
|
'PYMODULE'),
|
||||||
|
('pyimod02_importers',
|
||||||
|
'D:\\Projects\\cjgc_screenshot\\build\\沉降观测自动截图\\localpycs\\pyimod02_importers.pyc',
|
||||||
|
'PYMODULE'),
|
||||||
|
('pyimod03_ctypes',
|
||||||
|
'D:\\Projects\\cjgc_screenshot\\build\\沉降观测自动截图\\localpycs\\pyimod03_ctypes.pyc',
|
||||||
|
'PYMODULE'),
|
||||||
|
('pyimod04_pywin32',
|
||||||
|
'D:\\Projects\\cjgc_screenshot\\build\\沉降观测自动截图\\localpycs\\pyimod04_pywin32.pyc',
|
||||||
|
'PYMODULE'),
|
||||||
|
('pyiboot01_bootstrap',
|
||||||
|
'C:\\Program '
|
||||||
|
'Files\\Python312\\Lib\\site-packages\\PyInstaller\\loader\\pyiboot01_bootstrap.py',
|
||||||
|
'PYSOURCE'),
|
||||||
|
('pyi_rth_inspect',
|
||||||
|
'C:\\Program '
|
||||||
|
'Files\\Python312\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_inspect.py',
|
||||||
|
'PYSOURCE'),
|
||||||
|
('pyi_rth_pkgutil',
|
||||||
|
'C:\\Program '
|
||||||
|
'Files\\Python312\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pkgutil.py',
|
||||||
|
'PYSOURCE'),
|
||||||
|
('pyi_rth_multiprocessing',
|
||||||
|
'C:\\Program '
|
||||||
|
'Files\\Python312\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_multiprocessing.py',
|
||||||
|
'PYSOURCE'),
|
||||||
|
('scheduler', 'D:\\Projects\\cjgc_screenshot\\scheduler.py', 'PYSOURCE'),
|
||||||
|
('selenium\\webdriver\\common\\windows\\selenium-manager.exe',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\common\\windows\\selenium-manager.exe',
|
||||||
|
'BINARY'),
|
||||||
|
('python312.dll', 'C:\\Program Files\\Python312\\python312.dll', 'BINARY'),
|
||||||
|
('select.pyd', 'C:\\Program Files\\Python312\\DLLs\\select.pyd', 'EXTENSION'),
|
||||||
|
('_multiprocessing.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\_multiprocessing.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('pyexpat.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\pyexpat.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('_ssl.pyd', 'C:\\Program Files\\Python312\\DLLs\\_ssl.pyd', 'EXTENSION'),
|
||||||
|
('_hashlib.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\_hashlib.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('unicodedata.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\unicodedata.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('_decimal.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\_decimal.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('_socket.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\_socket.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('_lzma.pyd', 'C:\\Program Files\\Python312\\DLLs\\_lzma.pyd', 'EXTENSION'),
|
||||||
|
('_bz2.pyd', 'C:\\Program Files\\Python312\\DLLs\\_bz2.pyd', 'EXTENSION'),
|
||||||
|
('_ctypes.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\_ctypes.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('_queue.pyd', 'C:\\Program Files\\Python312\\DLLs\\_queue.pyd', 'EXTENSION'),
|
||||||
|
('_overlapped.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\_overlapped.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('_asyncio.pyd',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\_asyncio.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('charset_normalizer\\md__mypyc.cp312-win_amd64.pyd',
|
||||||
|
'C:\\Program '
|
||||||
|
'Files\\Python312\\Lib\\site-packages\\charset_normalizer\\md__mypyc.cp312-win_amd64.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('charset_normalizer\\md.cp312-win_amd64.pyd',
|
||||||
|
'C:\\Program '
|
||||||
|
'Files\\Python312\\Lib\\site-packages\\charset_normalizer\\md.cp312-win_amd64.pyd',
|
||||||
|
'EXTENSION'),
|
||||||
|
('_uuid.pyd', 'C:\\Program Files\\Python312\\DLLs\\_uuid.pyd', 'EXTENSION'),
|
||||||
|
('_wmi.pyd', 'C:\\Program Files\\Python312\\DLLs\\_wmi.pyd', 'EXTENSION'),
|
||||||
|
('api-ms-win-core-synch-l1-2-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-synch-l1-2-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-filesystem-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-filesystem-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-conio-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-conio-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('VCRUNTIME140.dll',
|
||||||
|
'C:\\Program Files\\Python312\\VCRUNTIME140.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-locale-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-locale-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-math-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-math-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-convert-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-convert-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-time-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-time-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-string-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-string-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-stdio-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-stdio-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-runtime-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-runtime-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-environment-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-environment-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-process-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-process-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-heap-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-heap-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-crt-utility-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-crt-utility-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('libcrypto-3.dll',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\libcrypto-3.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('libssl-3.dll',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\libssl-3.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('libffi-8.dll',
|
||||||
|
'C:\\Program Files\\Python312\\DLLs\\libffi-8.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('ucrtbase.dll', 'D:\\Resource\\JDK\\JavaJDK17\\bin\\ucrtbase.dll', 'BINARY'),
|
||||||
|
('api-ms-win-core-debug-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-debug-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-profile-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-profile-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-errorhandling-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-errorhandling-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-console-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-console-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-synch-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-synch-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-heap-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-heap-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-file-l2-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-file-l2-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-interlocked-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-interlocked-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-memory-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-memory-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-processenvironment-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-processenvironment-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-processthreads-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-processthreads-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-file-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-file-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-file-l1-2-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-file-l1-2-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-localization-l1-2-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-localization-l1-2-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-processthreads-l1-1-1.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-processthreads-l1-1-1.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-namedpipe-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-namedpipe-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-string-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-string-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-sysinfo-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-sysinfo-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-datetime-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-datetime-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-rtlsupport-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-rtlsupport-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-util-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-util-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-timezone-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-timezone-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-handle-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-handle-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('api-ms-win-core-libraryloader-l1-1-0.dll',
|
||||||
|
'D:\\Resource\\JDK\\JavaJDK17\\bin\\api-ms-win-core-libraryloader-l1-1-0.dll',
|
||||||
|
'BINARY'),
|
||||||
|
('certifi\\py.typed',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\certifi\\py.typed',
|
||||||
|
'DATA'),
|
||||||
|
('certifi\\cacert.pem',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\certifi\\cacert.pem',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\common\\mutation-listener.js',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\common\\mutation-listener.js',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\remote\\getAttribute.js',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\remote\\getAttribute.js',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\firefox\\webdriver_prefs.json',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\firefox\\webdriver_prefs.json',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\common\\devtools\\v137\\py.typed',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\common\\devtools\\v137\\py.typed',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\common\\devtools\\v138\\py.typed',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\common\\devtools\\v138\\py.typed',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\common\\linux\\selenium-manager',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\common\\linux\\selenium-manager',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\remote\\findElements.js',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\remote\\findElements.js',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\remote\\isDisplayed.js',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\remote\\isDisplayed.js',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\common\\devtools\\v139\\py.typed',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\common\\devtools\\v139\\py.typed',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\webdriver\\common\\macos\\selenium-manager',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\webdriver\\common\\macos\\selenium-manager',
|
||||||
|
'DATA'),
|
||||||
|
('selenium\\py.typed',
|
||||||
|
'C:\\Users\\ADMIN\\AppData\\Roaming\\Python\\Python312\\site-packages\\selenium\\py.typed',
|
||||||
|
'DATA'),
|
||||||
|
('base_library.zip',
|
||||||
|
'D:\\Projects\\cjgc_screenshot\\build\\沉降观测自动截图\\base_library.zip',
|
||||||
|
'DATA')],
|
||||||
|
'python312.dll',
|
||||||
|
False,
|
||||||
|
False,
|
||||||
|
False,
|
||||||
|
[],
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None)
|
||||||
BIN
build/沉降观测自动截图/PYZ-00.pyz
Normal file
BIN
build/沉降观测自动截图/PYZ-00.pyz
Normal file
Binary file not shown.
1793
build/沉降观测自动截图/PYZ-00.toc
Normal file
1793
build/沉降观测自动截图/PYZ-00.toc
Normal file
File diff suppressed because it is too large
Load Diff
BIN
build/沉降观测自动截图/base_library.zip
Normal file
BIN
build/沉降观测自动截图/base_library.zip
Normal file
Binary file not shown.
BIN
build/沉降观测自动截图/localpycs/pyimod01_archive.pyc
Normal file
BIN
build/沉降观测自动截图/localpycs/pyimod01_archive.pyc
Normal file
Binary file not shown.
BIN
build/沉降观测自动截图/localpycs/pyimod02_importers.pyc
Normal file
BIN
build/沉降观测自动截图/localpycs/pyimod02_importers.pyc
Normal file
Binary file not shown.
BIN
build/沉降观测自动截图/localpycs/pyimod03_ctypes.pyc
Normal file
BIN
build/沉降观测自动截图/localpycs/pyimod03_ctypes.pyc
Normal file
Binary file not shown.
BIN
build/沉降观测自动截图/localpycs/pyimod04_pywin32.pyc
Normal file
BIN
build/沉降观测自动截图/localpycs/pyimod04_pywin32.pyc
Normal file
Binary file not shown.
BIN
build/沉降观测自动截图/localpycs/struct.pyc
Normal file
BIN
build/沉降观测自动截图/localpycs/struct.pyc
Normal file
Binary file not shown.
64
build/沉降观测自动截图/warn-沉降观测自动截图.txt
Normal file
64
build/沉降观测自动截图/warn-沉降观测自动截图.txt
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
|
||||||
|
This file lists modules PyInstaller was not able to find. This does not
|
||||||
|
necessarily mean this module is required for running your program. Python and
|
||||||
|
Python 3rd-party packages include a lot of conditional or optional modules. For
|
||||||
|
example the module 'ntpath' only exists on Windows, whereas the module
|
||||||
|
'posixpath' only exists on Posix systems.
|
||||||
|
|
||||||
|
Types if import:
|
||||||
|
* top-level: imported at the top-level - look at these first
|
||||||
|
* conditional: imported within an if-statement
|
||||||
|
* delayed: imported within a function
|
||||||
|
* optional: imported within a try-except-statement
|
||||||
|
|
||||||
|
IMPORTANT: Do NOT post this list to the issue-tracker. Use it as a basis for
|
||||||
|
tracking down the missing module yourself. Thanks!
|
||||||
|
|
||||||
|
missing module named pwd - imported by posixpath (delayed, conditional, optional), shutil (delayed, optional), tarfile (optional), pathlib (delayed, optional), subprocess (delayed, conditional, optional), netrc (delayed, conditional), getpass (delayed)
|
||||||
|
missing module named grp - imported by shutil (delayed, optional), tarfile (optional), pathlib (delayed, optional), subprocess (delayed, conditional, optional)
|
||||||
|
missing module named _posixsubprocess - imported by subprocess (conditional), multiprocessing.util (delayed)
|
||||||
|
missing module named fcntl - imported by subprocess (optional)
|
||||||
|
missing module named _posixshmem - imported by multiprocessing.resource_tracker (conditional), multiprocessing.shared_memory (conditional)
|
||||||
|
missing module named _scproxy - imported by urllib.request (conditional)
|
||||||
|
missing module named termios - imported by getpass (optional)
|
||||||
|
missing module named _sha512 - imported by random (optional)
|
||||||
|
missing module named multiprocessing.BufferTooShort - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
|
||||||
|
missing module named multiprocessing.AuthenticationError - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
|
||||||
|
missing module named _frozen_importlib_external - imported by importlib._bootstrap (delayed), importlib (optional), importlib.abc (optional), zipimport (top-level)
|
||||||
|
excluded module named _frozen_importlib - imported by importlib (optional), importlib.abc (optional), zipimport (top-level)
|
||||||
|
missing module named posix - imported by os (conditional, optional), posixpath (optional), shutil (conditional), importlib._bootstrap_external (conditional)
|
||||||
|
missing module named resource - imported by posix (top-level)
|
||||||
|
missing module named multiprocessing.get_context - imported by multiprocessing (top-level), multiprocessing.pool (top-level), multiprocessing.managers (top-level), multiprocessing.sharedctypes (top-level)
|
||||||
|
missing module named multiprocessing.TimeoutError - imported by multiprocessing (top-level), multiprocessing.pool (top-level)
|
||||||
|
missing module named multiprocessing.set_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
|
||||||
|
missing module named multiprocessing.get_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
|
||||||
|
missing module named pyimod02_importers - imported by C:\Program Files\Python312\Lib\site-packages\PyInstaller\hooks\rthooks\pyi_rth_pkgutil.py (delayed)
|
||||||
|
missing module named collections.Callable - imported by collections (optional), socks (optional)
|
||||||
|
missing module named simplejson - imported by requests.compat (conditional, optional)
|
||||||
|
missing module named dummy_threading - imported by requests.cookies (optional)
|
||||||
|
missing module named asyncio.DefaultEventLoopPolicy - imported by asyncio (delayed, conditional), asyncio.events (delayed, conditional)
|
||||||
|
missing module named annotationlib - imported by typing_extensions (conditional)
|
||||||
|
missing module named zstandard - imported by urllib3.util.request (optional), urllib3.response (optional)
|
||||||
|
missing module named compression - imported by urllib3.util.request (optional), urllib3.response (optional)
|
||||||
|
missing module named 'h2.events' - imported by urllib3.http2.connection (top-level)
|
||||||
|
missing module named 'h2.connection' - imported by urllib3.http2.connection (top-level)
|
||||||
|
missing module named h2 - imported by urllib3.http2.connection (top-level)
|
||||||
|
missing module named brotli - imported by urllib3.util.request (optional), urllib3.response (optional)
|
||||||
|
missing module named brotlicffi - imported by urllib3.util.request (optional), urllib3.response (optional)
|
||||||
|
missing module named win_inet_pton - imported by socks (conditional, optional)
|
||||||
|
missing module named cryptography - imported by urllib3.contrib.pyopenssl (top-level), requests (conditional, optional)
|
||||||
|
missing module named 'OpenSSL.crypto' - imported by urllib3.contrib.pyopenssl (delayed, conditional)
|
||||||
|
missing module named 'cryptography.x509' - imported by urllib3.contrib.pyopenssl (delayed, optional)
|
||||||
|
missing module named OpenSSL - imported by urllib3.contrib.pyopenssl (top-level)
|
||||||
|
missing module named 'pyodide.ffi' - imported by urllib3.contrib.emscripten.fetch (delayed, optional)
|
||||||
|
missing module named pyodide - imported by urllib3.contrib.emscripten.fetch (top-level)
|
||||||
|
missing module named js - imported by urllib3.contrib.emscripten.fetch (top-level)
|
||||||
|
missing module named wsaccel - imported by websocket._utils (optional)
|
||||||
|
missing module named 'python_socks.sync' - imported by websocket._http (optional)
|
||||||
|
missing module named 'python_socks._types' - imported by websocket._http (optional)
|
||||||
|
missing module named python_socks - imported by websocket._http (optional)
|
||||||
|
missing module named 'wsaccel.xormask' - imported by websocket._abnf (optional)
|
||||||
|
missing module named _winreg - imported by platform (delayed, optional), selenium.webdriver.firefox.firefox_binary (delayed, optional)
|
||||||
|
missing module named vms_lib - imported by platform (delayed, optional)
|
||||||
|
missing module named 'java.lang' - imported by platform (delayed, optional)
|
||||||
|
missing module named java - imported by platform (delayed)
|
||||||
21916
build/沉降观测自动截图/xref-沉降观测自动截图.html
Normal file
21916
build/沉降观测自动截图/xref-沉降观测自动截图.html
Normal file
File diff suppressed because it is too large
Load Diff
BIN
build/沉降观测自动截图/沉降观测自动截图.pkg
Normal file
BIN
build/沉降观测自动截图/沉降观测自动截图.pkg
Normal file
Binary file not shown.
347
create_a_link.py
347
create_a_link.py
@@ -1,347 +0,0 @@
|
|||||||
import subprocess
|
|
||||||
import re
|
|
||||||
import time
|
|
||||||
import requests
|
|
||||||
import json
|
|
||||||
from appium import webdriver
|
|
||||||
from appium.webdriver.common.appiumby import AppiumBy
|
|
||||||
from appium.options.android import UiAutomator2Options
|
|
||||||
from selenium.webdriver.support.ui import WebDriverWait
|
|
||||||
from selenium.webdriver.support import expected_conditions as EC
|
|
||||||
from urllib3.connection import port_by_scheme
|
|
||||||
|
|
||||||
|
|
||||||
# =======================
|
|
||||||
# 基础工具函数
|
|
||||||
# =======================
|
|
||||||
|
|
||||||
def run_command(command):
|
|
||||||
"""执行系统命令并返回输出"""
|
|
||||||
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
||||||
return result.stdout.strip()
|
|
||||||
|
|
||||||
|
|
||||||
# =======================
|
|
||||||
# API请求函数
|
|
||||||
# =======================
|
|
||||||
|
|
||||||
def get_new_port(yh_id):
|
|
||||||
"""从服务器获取新的端口号"""
|
|
||||||
url = "https://engineering.yuxindazhineng.com/index/index/get_yh_port"
|
|
||||||
headers = {
|
|
||||||
"Content-Type": "application/x-www-form-urlencoded"
|
|
||||||
}
|
|
||||||
data = {
|
|
||||||
"yh_id": yh_id
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
|
||||||
print(f"🔍 查询服务器新端口号,用户ID: {yh_id}")
|
|
||||||
response = requests.post(url, headers=headers, data=data, timeout=10)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
result = response.json()
|
|
||||||
if result.get("code") == 0:
|
|
||||||
print(f"✅ 查询成功,新端口号: {result.get('data', '未知')}")
|
|
||||||
return result.get("data", None)
|
|
||||||
else:
|
|
||||||
print(f"❌ 查询失败: {result.get('msg', '未知错误')}")
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
print(f"❌ 服务器响应错误: {response.status_code}")
|
|
||||||
return None
|
|
||||||
except requests.exceptions.RequestException as e:
|
|
||||||
print(f"❌ 网络请求失败: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_accounts_from_server(yh_id):
|
|
||||||
"""从服务器获取账户信息"""
|
|
||||||
url = "http://www.yuxindazhineng.com:3002/api/accounts/get_uplaod_data"
|
|
||||||
headers = {
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
}
|
|
||||||
data = {
|
|
||||||
"yh_id": yh_id
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
|
||||||
print(f"🔍 查询服务器账户信息,用户ID: {yh_id}")
|
|
||||||
response = requests.post(url, headers=headers, json=data, timeout=10)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
result = response.json()
|
|
||||||
if result.get("code") == 0:
|
|
||||||
print(f"✅ 查询成功,找到 {result.get('total', 0)} 个账户")
|
|
||||||
return result.get("data", [])
|
|
||||||
else:
|
|
||||||
print(f"❌ 查询失败: {result.get('message', '未知错误')}")
|
|
||||||
return []
|
|
||||||
else:
|
|
||||||
print(f"❌ 服务器响应错误: {response.status_code}")
|
|
||||||
return []
|
|
||||||
except requests.exceptions.RequestException as e:
|
|
||||||
print(f"❌ 网络请求失败: {e}")
|
|
||||||
return []
|
|
||||||
except json.JSONDecodeError as e:
|
|
||||||
print(f"❌ JSON解析失败: {e}")
|
|
||||||
return []
|
|
||||||
|
|
||||||
|
|
||||||
def update_device_info(account_id, device_name, device_port, device_ip):
|
|
||||||
"""更新设备信息到服务器"""
|
|
||||||
url = "http://www.yuxindazhineng.com:3002/api/accounts/update"
|
|
||||||
headers = {
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
}
|
|
||||||
data = {
|
|
||||||
"account_id": str(account_id),
|
|
||||||
"account_data": {
|
|
||||||
"device_name": str(device_name),
|
|
||||||
"device_port": str(device_port),
|
|
||||||
"device_ip": str(device_ip)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
|
||||||
print(f"🔄 更新设备信息,账户ID: {account_id}")
|
|
||||||
print(f" 设备信息: 名称={device_name}, 端口={device_port}, IP={device_ip}")
|
|
||||||
|
|
||||||
response = requests.post(url, headers=headers, json=data, timeout=10)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
result = response.json()
|
|
||||||
if result.get("code") == 0:
|
|
||||||
print(f"✅ 更新成功: {result.get('message', '未知信息')}")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
print(f"❌ 更新失败: {result.get('message', '未知错误')}")
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
print(f"❌ 服务器响应错误: {response.status_code}")
|
|
||||||
return False
|
|
||||||
except requests.exceptions.RequestException as e:
|
|
||||||
print(f"❌ 网络请求失败: {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
# =======================
|
|
||||||
# Appium 启动
|
|
||||||
# =======================
|
|
||||||
|
|
||||||
def start_appium():
|
|
||||||
print("🚀 启动 Appium Server ...")
|
|
||||||
subprocess.Popen(
|
|
||||||
["appium.cmd", "-a", "127.0.0.1", "-p", "4723"],
|
|
||||||
stdout=subprocess.DEVNULL,
|
|
||||||
stderr=subprocess.DEVNULL
|
|
||||||
)
|
|
||||||
time.sleep(5) # 给 Appium 启动时间
|
|
||||||
print("✅ Appium Server 已启动")
|
|
||||||
|
|
||||||
|
|
||||||
# =======================
|
|
||||||
# 启动沉降观测 App
|
|
||||||
# =======================
|
|
||||||
|
|
||||||
def start_settlement_app(device_id, device_ip, device_port):
|
|
||||||
print(f"📱 使用 Appium 连接设备: {device_id}")
|
|
||||||
|
|
||||||
options = UiAutomator2Options()
|
|
||||||
options.platform_name = "Android"
|
|
||||||
options.device_name = device_id
|
|
||||||
options.udid = device_id
|
|
||||||
|
|
||||||
# ⚠️ TODO:替换为你的真实信息
|
|
||||||
options.app_package = "com.bjjw.cjgc"
|
|
||||||
options.app_activity = ".activity.LoginActivity"
|
|
||||||
|
|
||||||
options.automation_name = "UiAutomator2"
|
|
||||||
options.no_reset = True
|
|
||||||
options.auto_grant_permissions = True
|
|
||||||
options.new_command_timeout = 28800
|
|
||||||
|
|
||||||
# 超时增强(无线 ADB 必须)
|
|
||||||
options.set_capability("uiautomator2ServerLaunchTimeout", 60000)
|
|
||||||
options.set_capability("adbExecTimeout", 120000)
|
|
||||||
|
|
||||||
driver = webdriver.Remote(
|
|
||||||
"http://127.0.0.1:4723",
|
|
||||||
options=options
|
|
||||||
)
|
|
||||||
|
|
||||||
# 使用ADB命令启动Activity
|
|
||||||
try:
|
|
||||||
adb_command = f"adb -s {device_id} shell am start -n com.bjjw.cjgc/.activity.LoginActivity"
|
|
||||||
result = subprocess.run(adb_command, shell=True, capture_output=True, text=True)
|
|
||||||
if result.returncode == 0:
|
|
||||||
time.sleep(1) # 等待Activity启动
|
|
||||||
except Exception:
|
|
||||||
return False
|
|
||||||
|
|
||||||
print("✅ 沉降观测 App 已成功启动")
|
|
||||||
|
|
||||||
# =======================
|
|
||||||
# 获取用户名文本框内容
|
|
||||||
# =======================
|
|
||||||
app_username = None
|
|
||||||
try:
|
|
||||||
print("🔍 尝试获取用户名文本框内容...")
|
|
||||||
|
|
||||||
# 创建显式等待对象
|
|
||||||
wait = WebDriverWait(driver, 15) # 最多等待15秒
|
|
||||||
|
|
||||||
# 等待用户名文本框可点击
|
|
||||||
username_field = wait.until(
|
|
||||||
EC.element_to_be_clickable((AppiumBy.ID, "com.bjjw.cjgc:id/et_user_name"))
|
|
||||||
)
|
|
||||||
|
|
||||||
# 获取文本框中的文本内容
|
|
||||||
app_username = username_field.text
|
|
||||||
|
|
||||||
# 如果文本框是空的,尝试使用get_attribute获取文本
|
|
||||||
if not app_username:
|
|
||||||
app_username = username_field.get_attribute("text")
|
|
||||||
|
|
||||||
# 如果还是空的,尝试获取其他属性
|
|
||||||
if not app_username:
|
|
||||||
app_username = username_field.get_attribute("content-desc") or username_field.get_attribute("label")
|
|
||||||
|
|
||||||
if app_username:
|
|
||||||
print(f"✅ 成功获取到用户名: {app_username}")
|
|
||||||
else:
|
|
||||||
print("⚠️ 用户名文本框为空")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ 获取用户名失败: {e}")
|
|
||||||
|
|
||||||
return driver, app_username
|
|
||||||
|
|
||||||
|
|
||||||
# =======================
|
|
||||||
# 无线 ADB 建链主流程
|
|
||||||
# =======================
|
|
||||||
|
|
||||||
def setup_adb_wireless(yh_id="68c0dbfdb7cbcd616e7c5ab5"):
|
|
||||||
port = get_new_port(yh_id)
|
|
||||||
# port = 3435
|
|
||||||
print(f"🚀 开始无线 ADB 建链(端口 {port})")
|
|
||||||
print(f"📋 用户ID: {yh_id}")
|
|
||||||
|
|
||||||
# 从服务器获取账户信息
|
|
||||||
accounts = get_accounts_from_server(yh_id)
|
|
||||||
if not accounts:
|
|
||||||
print("❌ 未从服务器获取到账户信息,终止流程")
|
|
||||||
return
|
|
||||||
|
|
||||||
devices_output = run_command("adb devices")
|
|
||||||
lines = devices_output.splitlines()[1:]
|
|
||||||
|
|
||||||
usb_devices = []
|
|
||||||
|
|
||||||
for line in lines:
|
|
||||||
if not line.strip():
|
|
||||||
continue
|
|
||||||
|
|
||||||
device_id = line.split()[0]
|
|
||||||
|
|
||||||
# 跳过已经是无线的
|
|
||||||
if ":" in device_id:
|
|
||||||
continue
|
|
||||||
|
|
||||||
usb_devices.append(device_id)
|
|
||||||
|
|
||||||
if not usb_devices:
|
|
||||||
print("❌ 未检测到 USB 设备")
|
|
||||||
return
|
|
||||||
|
|
||||||
for serial in usb_devices:
|
|
||||||
print(f"\n🔎 处理设备: {serial}")
|
|
||||||
|
|
||||||
# 获取 WLAN IP
|
|
||||||
ip_info = run_command(f"adb -s {serial} shell ip addr show wlan0")
|
|
||||||
ip_match = re.search(r'inet\s+(\d+\.\d+\.\d+\.\d+)', ip_info)
|
|
||||||
|
|
||||||
if not ip_match:
|
|
||||||
print("⚠️ 获取 IP 失败,请确认已连接 WiFi")
|
|
||||||
continue
|
|
||||||
|
|
||||||
device_ip = ip_match.group(1)
|
|
||||||
print(f"📍 设备 IP: {device_ip}")
|
|
||||||
|
|
||||||
# 切 TCP 模式
|
|
||||||
run_command(f"adb -s {serial} tcpip {port}")
|
|
||||||
time.sleep(2)
|
|
||||||
|
|
||||||
# 无线连接
|
|
||||||
connect_result = run_command(f"adb connect {device_ip}:{port}")
|
|
||||||
|
|
||||||
if "connected" not in connect_result.lower():
|
|
||||||
print(f"❌ 无线连接失败: {connect_result}")
|
|
||||||
continue
|
|
||||||
|
|
||||||
wireless_id = f"{device_ip}:{port}"
|
|
||||||
print(f"✅ 无线 ADB 成功: {wireless_id}")
|
|
||||||
|
|
||||||
# ===== 后续自动化 =====
|
|
||||||
start_appium()
|
|
||||||
driver, app_username = start_settlement_app(wireless_id, device_ip, port)
|
|
||||||
|
|
||||||
if not app_username:
|
|
||||||
print("⚠️ 未获取到App中的用户名,跳过服务器更新")
|
|
||||||
continue
|
|
||||||
|
|
||||||
# 在账户列表中查找匹配的用户名
|
|
||||||
matched_account = None
|
|
||||||
for account in accounts:
|
|
||||||
if account.get("username") == app_username:
|
|
||||||
matched_account = account
|
|
||||||
break
|
|
||||||
|
|
||||||
if not matched_account:
|
|
||||||
print(f"❌ 未找到与用户名 '{app_username}' 匹配的账户")
|
|
||||||
continue
|
|
||||||
|
|
||||||
print(f"✅ 找到匹配账户: {matched_account.get('cl_name')} ({matched_account.get('username')})")
|
|
||||||
print(f" account_id: {matched_account.get('account_id')}")
|
|
||||||
|
|
||||||
# 更新设备信息到服务器
|
|
||||||
device_name = serial # 使用设备序列号作为设备名称
|
|
||||||
|
|
||||||
# 构建更新数据
|
|
||||||
update_data = {
|
|
||||||
"account_id": matched_account.get("account_id"),
|
|
||||||
"device_name": device_name,
|
|
||||||
"device_port": port,
|
|
||||||
"device_ip": device_ip
|
|
||||||
}
|
|
||||||
|
|
||||||
success = update_device_info(
|
|
||||||
account_id=matched_account.get("account_id"),
|
|
||||||
device_name=device_name,
|
|
||||||
device_port=port,
|
|
||||||
device_ip=device_ip
|
|
||||||
)
|
|
||||||
|
|
||||||
if success:
|
|
||||||
print(f"🎉 所有操作完成! 账户 {matched_account.get('username')} 的设备信息已更新")
|
|
||||||
else:
|
|
||||||
print(f"⚠️ 设备信息更新失败,但无线连接和App启动已完成")
|
|
||||||
|
|
||||||
# 关闭Appium连接
|
|
||||||
if driver:
|
|
||||||
print("🔄 关闭Appium连接...")
|
|
||||||
driver.quit()
|
|
||||||
|
|
||||||
break # 处理完第一个设备后退出,如需处理多个设备可移除此行
|
|
||||||
|
|
||||||
|
|
||||||
# =======================
|
|
||||||
# 程序入口
|
|
||||||
# =======================
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
# 配置参数
|
|
||||||
|
|
||||||
USER_ID = "68c0dbfdb7cbcd616e7c5ab5" # 替换为实际的用户ID
|
|
||||||
|
|
||||||
setup_adb_wireless(USER_ID)
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
# -*- mode: python ; coding: utf-8 -*-
|
|
||||||
|
|
||||||
|
|
||||||
a = Analysis(
|
|
||||||
['create_a_link.py'],
|
|
||||||
pathex=[],
|
|
||||||
binaries=[],
|
|
||||||
datas=[],
|
|
||||||
hiddenimports=[],
|
|
||||||
hookspath=[],
|
|
||||||
hooksconfig={},
|
|
||||||
runtime_hooks=[],
|
|
||||||
excludes=[],
|
|
||||||
noarchive=False,
|
|
||||||
optimize=0,
|
|
||||||
)
|
|
||||||
pyz = PYZ(a.pure)
|
|
||||||
|
|
||||||
exe = EXE(
|
|
||||||
pyz,
|
|
||||||
a.scripts,
|
|
||||||
a.binaries,
|
|
||||||
a.datas,
|
|
||||||
[],
|
|
||||||
name='create_a_link',
|
|
||||||
debug=False,
|
|
||||||
bootloader_ignore_signals=False,
|
|
||||||
strip=False,
|
|
||||||
upx=True,
|
|
||||||
upx_exclude=[],
|
|
||||||
runtime_tmpdir=None,
|
|
||||||
console=True,
|
|
||||||
disable_windowed_traceback=False,
|
|
||||||
argv_emulation=False,
|
|
||||||
target_arch=None,
|
|
||||||
codesign_identity=None,
|
|
||||||
entitlements_file=None,
|
|
||||||
)
|
|
||||||
BIN
dist/沉降观测自动上传.exe
vendored
BIN
dist/沉降观测自动上传.exe
vendored
Binary file not shown.
BIN
dist/create_a_link.exe → dist/沉降观测自动截图.exe
vendored
BIN
dist/create_a_link.exe → dist/沉降观测自动截图.exe
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
144
globals/apis.py
144
globals/apis.py
@@ -378,6 +378,107 @@ def get_user_max_variation(username: str) -> Optional[int]:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
|
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
|
||||||
|
# def get_line_info_and_save_global(user_name: str) -> bool:
|
||||||
|
# """
|
||||||
|
# 调用get_name_all接口,提取status=3的line_num和line_name存入全局字典
|
||||||
|
# :param user_name: 接口请求参数,如"wangshun"
|
||||||
|
# :return: 执行成功返回True,失败/异常返回False
|
||||||
|
# """
|
||||||
|
# # 接口基础配置
|
||||||
|
# api_url = "https://engineering.yuxindazhineng.com/index/index/get_name_all"
|
||||||
|
# request_params = {"user_name": user_name} # GET请求参数
|
||||||
|
# timeout = 10 # 请求超时时间(秒),避免卡进程
|
||||||
|
|
||||||
|
# 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格式,需解析为字典)
|
||||||
|
# try:
|
||||||
|
# response_data = response.json()
|
||||||
|
# except Exception as e:
|
||||||
|
# logging.error(f"接口返回内容非合法JSON,无法解析:{response.text},错误:{str(e)}")
|
||||||
|
# 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}")
|
||||||
|
# return False
|
||||||
|
# else:
|
||||||
|
# logging.warning(f"接口返回未知业务状态码:{business_code},请确认接口文档")
|
||||||
|
# return False
|
||||||
|
|
||||||
|
# # 5. 提取data字段,校验数据是否存在
|
||||||
|
# api_data_list = response_data.get("data")
|
||||||
|
# if not api_data_list:
|
||||||
|
# logging.warning("接口业务成功,但data字段为空或无数据")
|
||||||
|
# return False
|
||||||
|
|
||||||
|
# # 6. 校验data是否为列表类型
|
||||||
|
# if not isinstance(api_data_list, list):
|
||||||
|
# logging.error(f"data字段不是列表类型,实际类型:{type(api_data_list)},内容:{api_data_list}")
|
||||||
|
# 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且字段完整的线路信息")
|
||||||
|
# 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_line_info_and_save_global(user_name: str) -> bool:
|
def get_line_info_and_save_global(user_name: str) -> bool:
|
||||||
"""
|
"""
|
||||||
调用get_name_all接口,提取status=3的line_num和line_name存入全局字典
|
调用get_name_all接口,提取status=3的line_num和line_name存入全局字典
|
||||||
@@ -388,7 +489,10 @@ def get_line_info_and_save_global(user_name: str) -> bool:
|
|||||||
api_url = "https://engineering.yuxindazhineng.com/index/index/get_name_all"
|
api_url = "https://engineering.yuxindazhineng.com/index/index/get_name_all"
|
||||||
request_params = {"user_name": user_name} # GET请求参数
|
request_params = {"user_name": user_name} # GET请求参数
|
||||||
timeout = 10 # 请求超时时间(秒),避免卡进程
|
timeout = 10 # 请求超时时间(秒),避免卡进程
|
||||||
|
max_retries = 3 # 最大重试次数
|
||||||
|
retry_interval = 2 # 重试间隔(秒)
|
||||||
|
|
||||||
|
for retry in range(max_retries):
|
||||||
try:
|
try:
|
||||||
# 1. 发送GET请求
|
# 1. 发送GET请求
|
||||||
response = requests.get(
|
response = requests.get(
|
||||||
@@ -401,6 +505,10 @@ def get_line_info_and_save_global(user_name: str) -> bool:
|
|||||||
# 2. 校验HTTP状态码(先确保请求本身成功)
|
# 2. 校验HTTP状态码(先确保请求本身成功)
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
logging.error(f"接口请求失败,HTTP状态码异常:{response.status_code},响应内容:{response.text}")
|
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
|
return False
|
||||||
|
|
||||||
# 3. 解析JSON响应(接口返回是JSON格式,需解析为字典)
|
# 3. 解析JSON响应(接口返回是JSON格式,需解析为字典)
|
||||||
@@ -408,6 +516,10 @@ def get_line_info_and_save_global(user_name: str) -> bool:
|
|||||||
response_data = response.json()
|
response_data = response.json()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"接口返回内容非合法JSON,无法解析:{response.text},错误:{str(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
|
return False
|
||||||
|
|
||||||
# 4. 校验业务状态码(接口约定:code=0成功,-1失败)
|
# 4. 校验业务状态码(接口约定:code=0成功,-1失败)
|
||||||
@@ -416,20 +528,36 @@ def get_line_info_and_save_global(user_name: str) -> bool:
|
|||||||
logging.info("接口业务请求成功,开始解析数据")
|
logging.info("接口业务请求成功,开始解析数据")
|
||||||
elif business_code == -1:
|
elif business_code == -1:
|
||||||
logging.error(f"接口业务请求失败,业务状态码code=-1,返回数据:{response_data}")
|
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
|
return False
|
||||||
else:
|
else:
|
||||||
logging.warning(f"接口返回未知业务状态码:{business_code},请确认接口文档")
|
logging.warning(f"接口返回未知业务状态码:{business_code},请确认接口文档")
|
||||||
|
if retry < max_retries - 1:
|
||||||
|
logging.info(f"将在{retry_interval}秒后进行第{retry+2}次重试")
|
||||||
|
time.sleep(retry_interval)
|
||||||
|
continue
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 5. 提取data字段,校验数据是否存在
|
# 5. 提取data字段,校验数据是否存在
|
||||||
api_data_list = response_data.get("data")
|
api_data_list = response_data.get("data")
|
||||||
if not api_data_list:
|
if not api_data_list:
|
||||||
logging.warning("接口业务成功,但data字段为空或无数据")
|
logging.warning("接口业务成功,但data字段为空或无数据")
|
||||||
|
if retry < max_retries - 1:
|
||||||
|
logging.info(f"将在{retry_interval}秒后进行第{retry+2}次重试")
|
||||||
|
time.sleep(retry_interval)
|
||||||
|
continue
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 6. 校验data是否为列表类型
|
# 6. 校验data是否为列表类型
|
||||||
if not isinstance(api_data_list, list):
|
if not isinstance(api_data_list, list):
|
||||||
logging.error(f"data字段不是列表类型,实际类型:{type(api_data_list)},内容:{api_data_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
|
return False
|
||||||
|
|
||||||
found_valid_data = False
|
found_valid_data = False
|
||||||
@@ -466,17 +594,33 @@ def get_line_info_and_save_global(user_name: str) -> bool:
|
|||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
logging.warning("data列表中未找到任何status=3且字段完整的线路信息")
|
logging.warning("data列表中未找到任何status=3且字段完整的线路信息")
|
||||||
|
if retry < max_retries - 1:
|
||||||
|
logging.info(f"将在{retry_interval}秒后进行第{retry+2}次重试")
|
||||||
|
time.sleep(retry_interval)
|
||||||
|
continue
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 捕获所有请求相关异常(超时、连接失败、网络异常等)
|
# 捕获所有请求相关异常(超时、连接失败、网络异常等)
|
||||||
except requests.exceptions.Timeout:
|
except requests.exceptions.Timeout:
|
||||||
logging.error(f"调用get_name_all接口超时,超时时间:{timeout}秒,请求参数:{request_params}")
|
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
|
return False
|
||||||
except requests.exceptions.ConnectionError:
|
except requests.exceptions.ConnectionError:
|
||||||
logging.error(f"调用get_name_all接口连接失败,检查网络或接口地址是否正确:{api_url}")
|
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
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"调用get_name_all接口时发生未知异常:{str(e)}", exc_info=True) # exc_info=True打印异常堆栈,方便排查
|
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
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_accounts_from_server(yh_id):
|
def get_accounts_from_server(yh_id):
|
||||||
|
|||||||
@@ -126,6 +126,8 @@ def set_upload_success_breakpoint_list(success_list):
|
|||||||
"""设置上传成功的断点列表"""
|
"""设置上传成功的断点列表"""
|
||||||
thread_local.GLOBAL_UPLOAD_SUCCESS_BREAKPOINT_LIST = success_list
|
thread_local.GLOBAL_UPLOAD_SUCCESS_BREAKPOINT_LIST = success_list
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 为了保持 ,保留原有的全局变量名称
|
# 为了保持 ,保留原有的全局变量名称
|
||||||
# 但这些将不再被直接使用,而是通过上面的函数访问
|
# 但这些将不再被直接使用,而是通过上面的函数访问
|
||||||
GLOBAL_DEVICE_ID = "" # 设备ID
|
GLOBAL_DEVICE_ID = "" # 设备ID
|
||||||
|
|||||||
18
main.py
18
main.py
@@ -16,9 +16,7 @@ import permissions # 导入权限处理模块
|
|||||||
import globals.apis as apis
|
import globals.apis as apis
|
||||||
from globals.driver_utils import init_appium_driver, ensure_appium_server_running, safe_quit_driver, is_app_launched, launch_app_manually
|
from globals.driver_utils import init_appium_driver, ensure_appium_server_running, safe_quit_driver, is_app_launched, launch_app_manually
|
||||||
from page_objects.login_page import LoginPage
|
from page_objects.login_page import LoginPage
|
||||||
from page_objects.download_tabbar_page import DownloadTabbarPage
|
|
||||||
from page_objects.screenshot_page import ScreenshotPage
|
from page_objects.screenshot_page import ScreenshotPage
|
||||||
from page_objects.upload_config_page import UploadConfigPage
|
|
||||||
from page_objects.more_download_page import MoreDownloadPage
|
from page_objects.more_download_page import MoreDownloadPage
|
||||||
|
|
||||||
|
|
||||||
@@ -35,8 +33,14 @@ logging.basicConfig(
|
|||||||
class DeviceAutomation(object):
|
class DeviceAutomation(object):
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, device_id=None):
|
def __init__(self, device_id=None, project_name=None):
|
||||||
self.device_id = device_id
|
self.device_id = device_id
|
||||||
|
self.project_name = project_name
|
||||||
|
|
||||||
|
# 设置项目名称到全局变量
|
||||||
|
if project_name:
|
||||||
|
global_variable.set_current_project_name(project_name)
|
||||||
|
logging.info(f"设备 {self.device_id} 已设置项目名称: {project_name}")
|
||||||
|
|
||||||
# 初始化权限
|
# 初始化权限
|
||||||
if permissions.grant_appium_permissions(self.device_id):
|
if permissions.grant_appium_permissions(self.device_id):
|
||||||
@@ -62,9 +66,7 @@ class DeviceAutomation(object):
|
|||||||
# 初始化页面对象
|
# 初始化页面对象
|
||||||
logging.info(f"设备 {self.device_id} 开始初始化页面对象")
|
logging.info(f"设备 {self.device_id} 开始初始化页面对象")
|
||||||
self.login_page = LoginPage(self.driver, self.wait)
|
self.login_page = LoginPage(self.driver, self.wait)
|
||||||
self.download_tabbar_page = DownloadTabbarPage(self.driver, self.wait, self.device_id)
|
|
||||||
self.screenshot_page = ScreenshotPage(self.driver, self.wait, self.device_id)
|
self.screenshot_page = ScreenshotPage(self.driver, self.wait, self.device_id)
|
||||||
self.upload_config_page = UploadConfigPage(self.driver, self.wait, self.device_id)
|
|
||||||
self.more_download_page = MoreDownloadPage(self.driver, self.wait,self.device_id)
|
self.more_download_page = MoreDownloadPage(self.driver, self.wait,self.device_id)
|
||||||
logging.info(f"设备 {self.device_id} 所有页面对象初始化完成")
|
logging.info(f"设备 {self.device_id} 所有页面对象初始化完成")
|
||||||
|
|
||||||
@@ -246,13 +248,15 @@ class DeviceAutomation(object):
|
|||||||
safe_quit_driver(getattr(self, 'driver', None), self.device_id)
|
safe_quit_driver(getattr(self, 'driver', None), self.device_id)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def start_upload(device_id=None, upload_time=None):
|
def start_upload(device_id=None, upload_time=None, project_name=None):
|
||||||
"""
|
"""
|
||||||
供其他页面或模块调用的静态方法
|
供其他页面或模块调用的静态方法
|
||||||
执行完整的自动化流程
|
执行完整的自动化流程
|
||||||
|
|
||||||
参数:
|
参数:
|
||||||
device_id: 可选的设备ID,如果为None则自动获取
|
device_id: 可选的设备ID,如果为None则自动获取
|
||||||
|
upload_time: 上传时间
|
||||||
|
project_name: 项目名称
|
||||||
|
|
||||||
返回:
|
返回:
|
||||||
bool: 自动化流程执行结果(True/False)
|
bool: 自动化流程执行结果(True/False)
|
||||||
@@ -260,7 +264,7 @@ class DeviceAutomation(object):
|
|||||||
automation = None
|
automation = None
|
||||||
try:
|
try:
|
||||||
# 创建自动化实例
|
# 创建自动化实例
|
||||||
automation = DeviceAutomation(device_id=device_id)
|
automation = DeviceAutomation(device_id=device_id, project_name=project_name)
|
||||||
|
|
||||||
# 执行自动化流程
|
# 执行自动化流程
|
||||||
success = automation.run_automation()
|
success = automation.run_automation()
|
||||||
|
|||||||
Binary file not shown.
@@ -4,6 +4,7 @@ import logging
|
|||||||
import time
|
import time
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
|
import threading
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from appium.webdriver.common.appiumby import AppiumBy
|
from appium.webdriver.common.appiumby import AppiumBy
|
||||||
from selenium.common.exceptions import NoSuchElementException, TimeoutException
|
from selenium.common.exceptions import NoSuchElementException, TimeoutException
|
||||||
@@ -19,7 +20,7 @@ import globals.global_variable as global_variable # 导入全局变量模块
|
|||||||
class ScreenshotPage:
|
class ScreenshotPage:
|
||||||
def __init__(self, driver, wait, device_id=None):
|
def __init__(self, driver, wait, device_id=None):
|
||||||
self.driver = driver
|
self.driver = driver
|
||||||
self.wait = wait
|
self.wait = WebDriverWait(driver, 2)
|
||||||
self.device_id = device_id
|
self.device_id = device_id
|
||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger(__name__)
|
||||||
self.all_items = set()
|
self.all_items = set()
|
||||||
@@ -528,7 +529,7 @@ class ScreenshotPage:
|
|||||||
self.logger.error(f"设备 {device_id} 检查WiFi状态时发生错误: {str(e)}")
|
self.logger.error(f"设备 {device_id} 检查WiFi状态时发生错误: {str(e)}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def take_screenshot(self, filename_prefix="screenshot"):
|
def take_screenshot(self, filename_prefix="screenshot", date_str=None, time_str=None):
|
||||||
"""
|
"""
|
||||||
通过Appium驱动截取设备屏幕
|
通过Appium驱动截取设备屏幕
|
||||||
|
|
||||||
@@ -539,20 +540,58 @@ class ScreenshotPage:
|
|||||||
bool: 操作是否成功
|
bool: 操作是否成功
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# 创建测试结果目录
|
# 获取项目名称
|
||||||
screenshots_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../test_results/screenshots')
|
project_name = global_variable.get_current_project_name() or "默认项目"
|
||||||
if not os.path.exists(screenshots_dir):
|
|
||||||
os.makedirs(screenshots_dir)
|
# 获取当前日期(如果没有提供)
|
||||||
self.logger.info(f"创建截图目录: {screenshots_dir}")
|
if not date_str:
|
||||||
|
date_str = datetime.now().strftime("%Y%m%d")
|
||||||
|
|
||||||
|
# 获取当前时间(如果没有提供),并确保格式合法(不含冒号)
|
||||||
|
if not time_str:
|
||||||
|
time_str = datetime.now().strftime("%H%M%S")
|
||||||
|
else:
|
||||||
|
# 移除时间中的冒号,确保文件名合法
|
||||||
|
time_str = time_str.replace(":", "")
|
||||||
|
|
||||||
|
# 创建D盘下的截图目录结构:D:\uploadInfo\picture\项目名\年月日
|
||||||
|
screenshots_dir = os.path.join("D:\\", "uploadInfo", "picture", project_name, date_str)
|
||||||
|
|
||||||
|
# 确保目录存在
|
||||||
|
try:
|
||||||
|
os.makedirs(screenshots_dir, exist_ok=True)
|
||||||
|
self.logger.info(f"截图目录: {screenshots_dir}")
|
||||||
|
except Exception as dir_error:
|
||||||
|
self.logger.error(f"创建截图目录失败: {str(dir_error)}")
|
||||||
|
return False
|
||||||
|
line_code = global_variable.get_upload_breakpoint_dict().get(filename_prefix)
|
||||||
|
if not line_code:
|
||||||
|
self.logger.error(f"未找到与断点名称 {filename_prefix} 对应的线路编码")
|
||||||
|
line_code = "unknown"
|
||||||
|
|
||||||
# 截图保存
|
# 截图保存
|
||||||
screenshot_file = os.path.join(
|
screenshot_file = os.path.join(
|
||||||
screenshots_dir,
|
screenshots_dir,
|
||||||
f"{filename_prefix}_{datetime.now().strftime('%Y%m%d')}.png"
|
f"{line_code}_{filename_prefix}_{time_str}.png"
|
||||||
)
|
)
|
||||||
self.driver.save_screenshot(screenshot_file)
|
|
||||||
|
# 尝试保存截图
|
||||||
|
try:
|
||||||
|
success = self.driver.save_screenshot(screenshot_file)
|
||||||
|
if success:
|
||||||
self.logger.info(f"截图已保存: {screenshot_file}")
|
self.logger.info(f"截图已保存: {screenshot_file}")
|
||||||
|
# 验证文件是否真的存在
|
||||||
|
if os.path.exists(screenshot_file):
|
||||||
|
self.logger.info(f"截图文件验证存在: {screenshot_file}")
|
||||||
|
else:
|
||||||
|
self.logger.warning(f"截图文件保存成功但验证不存在: {screenshot_file}")
|
||||||
return True
|
return True
|
||||||
|
else:
|
||||||
|
self.logger.error(f"Appium截图保存失败: {screenshot_file}")
|
||||||
|
return False
|
||||||
|
except Exception as save_error:
|
||||||
|
self.logger.error(f"保存截图时发生错误: {str(save_error)}")
|
||||||
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"截图时发生错误: {str(e)}")
|
self.logger.error(f"截图时发生错误: {str(e)}")
|
||||||
@@ -591,117 +630,79 @@ class ScreenshotPage:
|
|||||||
self.logger.error(f"写入截图状态文件时发生错误: {str(e)}")
|
self.logger.error(f"写入截图状态文件时发生错误: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def wait_for_measurement_end(self, timeout=900):
|
def update_file_status(self, username, from_status, to_status):
|
||||||
"""
|
"""
|
||||||
等待按钮变成"测量结束",最多15分钟,包含驱动重新初始化机制
|
安全地更新 time.txt 中该用户的状态
|
||||||
|
例如: 将 'true' 改为 'running', 或将 'running' 改为 'done'
|
||||||
Args:
|
|
||||||
timeout: 超时时间,默认900秒(15分钟)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 是否成功等到测量结束按钮
|
|
||||||
"""
|
"""
|
||||||
try:
|
TIME_FILE_PATH = r"D:\uploadInfo\time.txt"
|
||||||
# 更新WebDriverWait等待时间为900秒
|
if not os.path.exists(TIME_FILE_PATH):
|
||||||
self.wait = WebDriverWait(self.driver, 900)
|
|
||||||
self.logger.info(f"设备等待测量结束按钮出现,最多等待 {timeout} 秒")
|
|
||||||
|
|
||||||
start_time = time.time()
|
|
||||||
reinit_attempts = 0
|
|
||||||
max_reinit_attempts = 3 # 最大重新初始化次数
|
|
||||||
|
|
||||||
while time.time() - start_time < timeout:
|
|
||||||
try:
|
|
||||||
# 使用XPath查找文本为"测量结束"的按钮
|
|
||||||
measurement_end_button = self.driver.find_element(
|
|
||||||
AppiumBy.XPATH,
|
|
||||||
"//android.widget.Button[@text='测量结束']"
|
|
||||||
)
|
|
||||||
|
|
||||||
if measurement_end_button.is_displayed() and measurement_end_button.is_enabled():
|
|
||||||
self.logger.info(f"设备检测到测量结束按钮")
|
|
||||||
return True
|
|
||||||
|
|
||||||
except NoSuchElementException:
|
|
||||||
# 按钮未找到,继续等待
|
|
||||||
pass
|
|
||||||
except Exception as e:
|
|
||||||
error_msg = str(e)
|
|
||||||
self.logger.warning(f"设备查找测量结束按钮时出现异常: {error_msg}")
|
|
||||||
|
|
||||||
# 检测是否是UiAutomator2服务崩溃
|
|
||||||
if 'UiAutomator2 server' in error_msg and 'instrumentation process is not running' in error_msg and reinit_attempts < max_reinit_attempts:
|
|
||||||
reinit_attempts += 1
|
|
||||||
self.logger.info(f"设备检测到UiAutomator2服务崩溃,尝试第 {reinit_attempts} 次重新初始化驱动")
|
|
||||||
|
|
||||||
# 尝试重新初始化驱动
|
|
||||||
if self._reinit_driver():
|
|
||||||
self.logger.info(f"设备驱动重新初始化成功")
|
|
||||||
else:
|
|
||||||
self.logger.error(f"设备驱动重新初始化失败")
|
|
||||||
# 继续尝试,而不是立即失败
|
|
||||||
|
|
||||||
# 等待一段时间后再次检查
|
|
||||||
time.sleep(3)
|
|
||||||
|
|
||||||
# 每30秒输出一次等待状态
|
|
||||||
if int(time.time() - start_time) % 30 == 0:
|
|
||||||
elapsed = int(time.time() - start_time)
|
|
||||||
self.logger.info(f"设备 {self.device_id} 已等待 {elapsed} 秒,仍在等待测量结束...")
|
|
||||||
|
|
||||||
self.logger.error(f"设备 {self.device_id} 等待测量结束按钮超时")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
success = False
|
||||||
|
file_lock = threading.Lock()
|
||||||
|
with file_lock:
|
||||||
|
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:
|
||||||
|
# 使用正则确保精准匹配用户名和结尾状态
|
||||||
|
# 匹配规则:行内包含该用户名,且该行以 from_status 结尾
|
||||||
|
if re.search(rf'\b{username}\b', line) and line.strip().endswith(from_status):
|
||||||
|
# 只替换行尾的那个状态词
|
||||||
|
line = re.sub(rf'{from_status}$', to_status, line.rstrip()) + '\n'
|
||||||
|
success = True
|
||||||
|
new_lines.append(line)
|
||||||
|
|
||||||
|
with open(TIME_FILE_PATH, 'w', encoding='utf-8') as f:
|
||||||
|
f.writelines(new_lines)
|
||||||
|
|
||||||
|
if success:
|
||||||
|
print(f"📝 [文件更新] 用户 {username}: {from_status} -> {to_status}")
|
||||||
|
return success
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"设备 {self.device_id} 等待测量结束时发生错误: {str(e)}")
|
print(f"❌ 更新文件状态失败 ({username}): {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _reinit_driver(self):
|
def update_upload_info_status(self, status):
|
||||||
"""
|
"""
|
||||||
重新初始化Appium驱动
|
更新D:/uploadInfo文件夹下的time.txt文件的状态
|
||||||
|
|
||||||
Returns:
|
参数:
|
||||||
bool: 是否成功重新初始化
|
status: 状态值,如"ok"或"again"
|
||||||
|
|
||||||
|
返回:
|
||||||
|
bool: 操作是否成功
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# 首先尝试关闭现有的驱动
|
# time.txt文件路径
|
||||||
if hasattr(self, 'driver') and self.driver:
|
time_file_path = "D:\\uploadInfo\\time.txt"
|
||||||
try:
|
|
||||||
self.driver.quit()
|
|
||||||
except:
|
|
||||||
self.logger.warning("关闭现有驱动时出现异常")
|
|
||||||
|
|
||||||
# 导入必要的模块
|
# 确保文件夹存在
|
||||||
from appium import webdriver
|
os.makedirs(os.path.dirname(time_file_path), exist_ok=True)
|
||||||
from appium.options.android import UiAutomator2Options
|
|
||||||
|
|
||||||
# 重新创建驱动配置
|
# 写入状态
|
||||||
options = UiAutomator2Options()
|
with open(time_file_path, 'w', encoding='utf-8') as f:
|
||||||
options.platform_name = "Android"
|
f.write(status)
|
||||||
options.device_name = self.device_id
|
|
||||||
options.app_package = "com.bjjw.cjgc"
|
|
||||||
options.app_activity = ".activity.LoginActivity"
|
|
||||||
options.automation_name = "UiAutomator2"
|
|
||||||
options.no_reset = True
|
|
||||||
options.auto_grant_permissions = True
|
|
||||||
options.new_command_timeout = 300
|
|
||||||
options.udid = self.device_id
|
|
||||||
|
|
||||||
# 重新连接驱动
|
self.logger.info(f"已更新上传状态文件: {time_file_path} -> {status}")
|
||||||
self.logger.info(f"正在重新初始化设备 {self.device_id} 的驱动...")
|
|
||||||
self.driver = webdriver.Remote("http://localhost:4723", options=options)
|
|
||||||
|
|
||||||
# 重新初始化等待对象
|
|
||||||
from selenium.webdriver.support.ui import WebDriverWait
|
|
||||||
self.wait = WebDriverWait(self.driver, 1)
|
|
||||||
|
|
||||||
self.logger.info(f"设备 {self.device_id} 驱动重新初始化完成")
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"设备 {self.device_id} 驱动重新初始化失败: {str(e)}")
|
self.logger.error(f"更新上传状态文件时发生错误: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def handle_confirmation_dialog(self, device_id, timeout=2):
|
def handle_confirmation_dialog(self, device_id, timeout=2):
|
||||||
"""
|
"""
|
||||||
处理确认弹窗,点击"是"按钮
|
处理确认弹窗,点击"是"按钮
|
||||||
@@ -808,7 +809,7 @@ class ScreenshotPage:
|
|||||||
if confirm_button and confirm_button.is_displayed() and confirm_button.is_enabled():
|
if confirm_button and confirm_button.is_displayed() and confirm_button.is_enabled():
|
||||||
self.logger.info(f"设备 {device_id} 点击确认弹窗的'是'按钮")
|
self.logger.info(f"设备 {device_id} 点击确认弹窗的'是'按钮")
|
||||||
confirm_button.click()
|
confirm_button.click()
|
||||||
time.sleep(1)
|
time.sleep(0.5)
|
||||||
|
|
||||||
# 验证弹窗是否消失
|
# 验证弹窗是否消失
|
||||||
try:
|
try:
|
||||||
@@ -828,7 +829,7 @@ class ScreenshotPage:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"设备 {device_id} 查找确认弹窗时出现异常: {str(e)}")
|
self.logger.warning(f"设备 {device_id} 查找确认弹窗时出现异常: {str(e)}")
|
||||||
|
|
||||||
time.sleep(1)
|
time.sleep(0.5)
|
||||||
|
|
||||||
self.logger.error(f"设备 {device_id} 等待返回确认弹窗超时")
|
self.logger.error(f"设备 {device_id} 等待返回确认弹窗超时")
|
||||||
return False
|
return False
|
||||||
@@ -1001,7 +1002,7 @@ class ScreenshotPage:
|
|||||||
|
|
||||||
|
|
||||||
# 3. 验证是否成功返回到上一页面
|
# 3. 验证是否成功返回到上一页面
|
||||||
time.sleep(1) # 等待页面跳转完成
|
time.sleep(0.5) # 等待页面跳转完成
|
||||||
|
|
||||||
# 可以添加页面验证逻辑,比如检查是否返回到预期的页面
|
# 可以添加页面验证逻辑,比如检查是否返回到预期的页面
|
||||||
# 这里可以根据实际应用添加特定的页面元素验证
|
# 这里可以根据实际应用添加特定的页面元素验证
|
||||||
@@ -1013,51 +1014,6 @@ class ScreenshotPage:
|
|||||||
self.logger.error(f"设备 {device_id} 执行返回导航步骤时发生错误: {str(e)}")
|
self.logger.error(f"设备 {device_id} 执行返回导航步骤时发生错误: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def scroll_to_bottom_and_screenshot(self, device_id):
|
|
||||||
"""
|
|
||||||
检测到测量结束后,下滑列表到最底端,点击最后一个spinner,再下滑一次,点击平差处理按钮后截图
|
|
||||||
|
|
||||||
Args:
|
|
||||||
device_id: 设备ID
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 操作是否成功
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
self.logger.info(f"设备 {device_id} 开始执行测量结束后的操作流程")
|
|
||||||
time.sleep(5)
|
|
||||||
|
|
||||||
# 1. 下滑列表到最底端
|
|
||||||
if not self.scroll_list_to_bottom(device_id):
|
|
||||||
self.logger.error(f"设备 {device_id} 下滑列表到底部失败")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 2. 点击最后一个spinner
|
|
||||||
if not self.click_last_spinner_with_retry(device_id):
|
|
||||||
self.logger.error(f"设备 {device_id} 点击最后一个spinner失败")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 3. 再下滑一次
|
|
||||||
if not self.scroll_down_once(device_id):
|
|
||||||
self.logger.warning(f"设备 {device_id} 再次下滑失败,但继续执行")
|
|
||||||
|
|
||||||
# 4. 点击平差处理按钮
|
|
||||||
if not self.click_adjustment_button(device_id):
|
|
||||||
self.logger.error(f"设备 {device_id} 点击平差处理按钮失败")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 5. 在点击平差处理按钮后截图
|
|
||||||
time.sleep(2) # 等待平差处理按钮点击后的界面变化
|
|
||||||
if not self.take_screenshot("after_adjustment_button_click"):
|
|
||||||
self.logger.error(f"设备 {device_id} 截图失败")
|
|
||||||
return False
|
|
||||||
|
|
||||||
self.logger.info(f"设备 {device_id} 测量结束后操作流程完成")
|
|
||||||
return True
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
self.logger.error(f"设备 {device_id} 执行测量结束后操作时发生错误: {str(e)}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def scroll_list_to_bottom(self, device_id, max_swipes=60):
|
def scroll_list_to_bottom(self, device_id, max_swipes=60):
|
||||||
"""
|
"""
|
||||||
@@ -1094,7 +1050,7 @@ class ScreenshotPage:
|
|||||||
'duration': 500
|
'duration': 500
|
||||||
})
|
})
|
||||||
|
|
||||||
time.sleep(0.5)
|
# time.sleep(0.5)
|
||||||
|
|
||||||
# 获取滑动后的子元素文本
|
# 获取滑动后的子元素文本
|
||||||
new_child_elements = list_view.find_elements(AppiumBy.CLASS_NAME, "android.widget.TextView")
|
new_child_elements = list_view.find_elements(AppiumBy.CLASS_NAME, "android.widget.TextView")
|
||||||
@@ -1129,7 +1085,7 @@ class ScreenshotPage:
|
|||||||
if self.click_last_spinner(device_id):
|
if self.click_last_spinner(device_id):
|
||||||
return True
|
return True
|
||||||
self.logger.warning(f"设备 {device_id} 第{attempt + 1}次点击失败,准备重试")
|
self.logger.warning(f"设备 {device_id} 第{attempt + 1}次点击失败,准备重试")
|
||||||
time.sleep(1) # 重试前等待
|
time.sleep(0.5) # 重试前等待
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"设备 {device_id} 第{attempt + 1}次尝试失败: {str(e)}")
|
self.logger.error(f"设备 {device_id} 第{attempt + 1}次尝试失败: {str(e)}")
|
||||||
|
|
||||||
@@ -1280,7 +1236,7 @@ class ScreenshotPage:
|
|||||||
'percent': 0.5
|
'percent': 0.5
|
||||||
})
|
})
|
||||||
|
|
||||||
time.sleep(1)
|
time.sleep(0.2)
|
||||||
self.logger.info(f"设备 {device_id} 额外下滑完成")
|
self.logger.info(f"设备 {device_id} 额外下滑完成")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -1380,7 +1336,7 @@ class ScreenshotPage:
|
|||||||
self.logger.info(f"设备 {device_id} 等待 {timeout} 秒未发现确认弹窗,可能没有弹窗,返回成功")
|
self.logger.info(f"设备 {device_id} 等待 {timeout} 秒未发现确认弹窗,可能没有弹窗,返回成功")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def load_line_time_mapping_dict(self, filename="20251022.1.CZSCZQ-3fhg0410.txt", log_directory="D:\\soft\\安卓时间修改-v0.7.13-1\\Logs\\202510", poll_interval=120, max_wait_time=18000):
|
def load_line_time_mapping_dict(self, filename="20251022.1.CZSCZQ-3fhg0410.txt", log_directory="D:\\uploadInfo\\Logs\\202510", poll_interval=120, max_wait_time=18000):
|
||||||
"""
|
"""
|
||||||
加载指定文件中的线路编码和时间到全局字典
|
加载指定文件中的线路编码和时间到全局字典
|
||||||
参数:
|
参数:
|
||||||
@@ -1466,11 +1422,11 @@ class ScreenshotPage:
|
|||||||
"""执行截图页面管理操作"""
|
"""执行截图页面管理操作"""
|
||||||
try:
|
try:
|
||||||
# 加载指定文件中的线路编码和时间到全局字典
|
# 加载指定文件中的线路编码和时间到全局字典
|
||||||
if not self.load_line_time_mapping_dict("20251022.1.CZSCZQ-3fhg0410.txt", "D:\\soft\\安卓时间修改-v0.7.13-1\\Logs\\202510"):
|
if not self.load_line_time_mapping_dict("20251022.1.CZSCZQ-3fhg0410.txt", "D:\\uploadInfo\\Logs\\202510"):
|
||||||
self.logger.error(f"设备 {device_id} 加载线路时间映射字典失败")
|
self.logger.error(f"设备 {device_id} 加载线路时间映射字典失败")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
time.sleep(5)
|
# time.sleep(5)
|
||||||
|
|
||||||
# 循环检查数据数量是否一致,直到获取到完整数据
|
# 循环检查数据数量是否一致,直到获取到完整数据
|
||||||
retry_count = 0
|
retry_count = 0
|
||||||
@@ -1496,7 +1452,7 @@ class ScreenshotPage:
|
|||||||
time.sleep(60) # 等待3分钟
|
time.sleep(60) # 等待3分钟
|
||||||
|
|
||||||
# 重新加载文件
|
# 重新加载文件
|
||||||
if not self.load_line_time_mapping_dict("20251022.1.CZSCZQ-3fhg0410.txt", "D:\\soft\\安卓时间修改-v0.7.13-1\\Logs\\202510"):
|
if not self.load_line_time_mapping_dict("20251022.1.CZSCZQ-3fhg0410.txt", "D:\\uploadInfo\\Logs\\202510"):
|
||||||
self.logger.error(f"设备 {device_id} 重新加载线路时间映射字典失败")
|
self.logger.error(f"设备 {device_id} 重新加载线路时间映射字典失败")
|
||||||
else:
|
else:
|
||||||
self.logger.info(f"设备 {device_id} 重新加载完成,新的线路时间数量: {len(global_variable.get_line_time_mapping_dict())}")
|
self.logger.info(f"设备 {device_id} 重新加载完成,新的线路时间数量: {len(global_variable.get_line_time_mapping_dict())}")
|
||||||
@@ -1524,98 +1480,90 @@ class ScreenshotPage:
|
|||||||
})
|
})
|
||||||
|
|
||||||
# 开始循环
|
# 开始循环
|
||||||
|
all_success = True
|
||||||
for breakpoint_name in global_variable.get_upload_breakpoint_dict().keys():
|
for breakpoint_name in global_variable.get_upload_breakpoint_dict().keys():
|
||||||
self.logger.info(f"开始处理要平差截图的断点 {breakpoint_name}")
|
self.logger.info(f"开始处理要平差截图的断点 {breakpoint_name}")
|
||||||
# 把断点名称给find_keyword
|
# 把断点名称给find_keyword
|
||||||
if not self.find_keyword(breakpoint_name):
|
if not self.find_keyword(breakpoint_name):
|
||||||
self.logger.error(f"设备 {device_id} 未找到包含 {breakpoint_name} 的文件名")
|
self.logger.error(f"设备 {device_id} 未找到包含 {breakpoint_name} 的文件名")
|
||||||
return False
|
all_success = False
|
||||||
|
continue
|
||||||
|
|
||||||
if not self.handle_measurement_dialog():
|
if not self.handle_measurement_dialog():
|
||||||
self.logger.error(f"设备 {device_id} 处理测量弹窗失败")
|
self.logger.error(f"设备 {device_id} 处理测量弹窗失败")
|
||||||
return False
|
all_success = False
|
||||||
|
continue
|
||||||
|
|
||||||
if not self.check_apply_btn():
|
if not self.check_apply_btn():
|
||||||
self.logger.error(f"设备 {device_id} 检查平差处理按钮失败")
|
self.logger.error(f"设备 {device_id} 检查平差处理按钮失败")
|
||||||
return False
|
all_success = False
|
||||||
|
self.click_back_button(device_id)
|
||||||
|
continue
|
||||||
|
|
||||||
# 根据断点名称在get_upload_breakpoint_dict()中获取线路编码
|
# 根据断点名称在get_upload_breakpoint_dict()中获取线路编码
|
||||||
line_code = global_variable.get_upload_breakpoint_dict().get(breakpoint_name)
|
line_code = global_variable.get_upload_breakpoint_dict().get(breakpoint_name)
|
||||||
if not line_code:
|
if not line_code:
|
||||||
self.logger.error(f"设备 {device_id} 未找到断点 {breakpoint_name} 对应的线路编码")
|
self.logger.error(f"设备 {device_id} 未找到断点 {breakpoint_name} 对应的线路编码")
|
||||||
return False
|
all_success = False
|
||||||
|
continue
|
||||||
|
|
||||||
# 根据线路编码查找对应的时间
|
# 根据线路编码查找对应的时间
|
||||||
date_str, time_str = self.get_line_end_time(line_code)
|
date_str, time_str = self.get_line_end_time(line_code)
|
||||||
if not time_str or not date_str:
|
if not time_str or not date_str:
|
||||||
self.logger.error(f"设备 {device_id} 未找到线路 {line_code} 对应的时间")
|
self.logger.error(f"设备 {device_id} 未找到线路 {line_code} 对应的时间")
|
||||||
return False
|
all_success = False
|
||||||
|
continue
|
||||||
|
|
||||||
# 修改时间
|
# 修改时间
|
||||||
if not self.set_device_time(device_id, time_str, date_str):
|
if not self.set_device_time(device_id, time_str, date_str):
|
||||||
self.logger.error(f"设备 {device_id} 设置设备时间失败")
|
self.logger.error(f"设备 {device_id} 设置设备时间失败")
|
||||||
return False
|
all_success = False
|
||||||
|
continue
|
||||||
|
|
||||||
# 滑动列表到底部
|
# 滑动列表到底部
|
||||||
if not self.scroll_list_to_bottom(device_id):
|
if not self.scroll_list_to_bottom(device_id):
|
||||||
self.logger.error(f"设备 {device_id} 下滑列表到底部失败")
|
self.logger.error(f"设备 {device_id} 下滑列表到底部失败")
|
||||||
return False
|
all_success = False
|
||||||
|
continue
|
||||||
|
|
||||||
# 2. 点击最后一个spinner
|
# 2. 点击最后一个spinner
|
||||||
if not self.click_last_spinner_with_retry(device_id):
|
if not self.click_last_spinner_with_retry(device_id):
|
||||||
self.logger.error(f"设备 {device_id} 点击最后一个spinner失败")
|
self.logger.error(f"设备 {device_id} 点击最后一个spinner失败")
|
||||||
return False
|
all_success = False
|
||||||
|
continue
|
||||||
|
|
||||||
# 3. 再下滑一次
|
# 3. 再下滑一次
|
||||||
if not self.scroll_down_once(device_id):
|
if not self.scroll_down_once(device_id):
|
||||||
self.logger.warning(f"设备 {device_id} 再次下滑失败,但继续执行")
|
self.logger.warning(f"设备 {device_id} 再次下滑失败,但继续执行")
|
||||||
|
|
||||||
# # 4. 点击平差处理按钮
|
|
||||||
# if not self.click_adjustment_button(device_id):
|
|
||||||
# self.logger.error(f"设备 {device_id} 点击平差处理按钮失败")
|
|
||||||
# return False
|
|
||||||
|
|
||||||
# # 检查是否在测量页面,在就重新执行选择断点,滑动列表到底部,点击最后一个spinner, 再下滑一次,点击平差处理按钮平差
|
|
||||||
# if not self.handle_back_navigation(breakpoint_name, device_id):
|
|
||||||
# self.logger.error(f"{breakpoint_name}平差失败,未截图")
|
|
||||||
# return False
|
|
||||||
|
|
||||||
|
|
||||||
# # 检测并处理"是 保留成果"弹窗
|
|
||||||
# if not self.handle_adjustment_result_dialog():
|
|
||||||
# self.logger.error("处理平差结果弹窗失败")
|
|
||||||
# return False
|
|
||||||
|
|
||||||
# # 平差完成,将断点数据保存到上传列表中
|
|
||||||
# if not self.add_breakpoint_to_upload_list(breakpoint_name, line_code):
|
|
||||||
# self.logger.error(f"设备 {device_id} 保存断点 {breakpoint_name} 到上传列表失败")
|
|
||||||
# return False
|
|
||||||
|
|
||||||
# # 禁用WiFi
|
|
||||||
# if not self.disable_wifi(device_id):
|
|
||||||
# self.logger.error(f"设备 {device_id} 禁用WiFi失败")
|
|
||||||
# return False
|
|
||||||
|
|
||||||
# 平差处理完成后截图
|
# 平差处理完成后截图
|
||||||
time.sleep(3) # 等待平差处理按钮点击后的界面变化
|
time.sleep(0.2) # 等待平差处理按钮点击后的界面变化
|
||||||
logging.info("断点保存到上传列表成功,开始截图")
|
logging.info("断点保存到上传列表成功,开始截图")
|
||||||
if not self.take_screenshot(breakpoint_name):
|
# png_time = date_str + " " + time_str
|
||||||
|
if not self.take_screenshot(breakpoint_name, date_str, time_str):
|
||||||
self.logger.error(f"设备 {device_id} 截图失败")
|
self.logger.error(f"设备 {device_id} 截图失败")
|
||||||
self.write_screenshot_status(breakpoint_name, success=False)
|
self.write_screenshot_status(breakpoint_name, success=False)
|
||||||
return False
|
all_success = False
|
||||||
|
else:
|
||||||
self.write_screenshot_status(breakpoint_name, success=True)
|
self.write_screenshot_status(breakpoint_name, success=True)
|
||||||
|
|
||||||
# 点击返回按钮并处理弹窗
|
# 点击返回按钮并处理弹窗
|
||||||
if not self.execute_back_navigation_steps(device_id):
|
if not self.execute_back_navigation_steps(device_id):
|
||||||
self.logger.error(f"设备 {device_id} 处理返回按钮确认失败")
|
self.logger.error(f"设备 {device_id} 处理返回按钮确认失败")
|
||||||
return False
|
all_success = False
|
||||||
# 启用WiFi
|
# 启用WiFi
|
||||||
# if not self.enable_wifi(device_id):
|
# if not self.enable_wifi(device_id):
|
||||||
# self.logger.error(f"设备 {device_id} 启用WiFi失败")
|
# self.logger.error(f"设备 {device_id} 启用WiFi失败")
|
||||||
# return False
|
# return False
|
||||||
|
|
||||||
self.logger.info(f"设备 {device_id} 截图页面操作执行完成")
|
# 根据截图结果更新time.txt文件状态
|
||||||
|
status = "ok" if all_success else "true"
|
||||||
|
# self.update_upload_info_status(status)
|
||||||
|
username = global_variable.get_username()
|
||||||
|
self.update_file_status(username, "running", status)
|
||||||
|
self.logger.info(f"{username} 截图完成状态为 {status}")
|
||||||
|
|
||||||
|
self.logger.info(f"设备 {device_id} 截图页面操作执行完成,状态: {status}")
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"设备 {device_id} 执行截图页面操作时出错: {str(e)}")
|
self.logger.error(f"设备 {device_id} 执行截图页面操作时出错: {str(e)}")
|
||||||
|
|||||||
63
scheduler.py
63
scheduler.py
@@ -73,7 +73,7 @@ def parse_time_config():
|
|||||||
for line in f:
|
for line in f:
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
# 匹配:用户名 时间 true (仅获取待处理任务)
|
# 匹配:用户名 时间 true (仅获取待处理任务)
|
||||||
match = re.search(r'(\w+)\s+(\d{1,2}:\d{2}:\d{2})\s+true$', line)
|
match = re.search(r'(\w+)\s+(\d{4}-\d{1,2}-\d{1,2}\s+\d{1,2}:\d{2}:\d{2})\s+true$', line)
|
||||||
if match:
|
if match:
|
||||||
username, scheduled_time = match.group(1), match.group(2)
|
username, scheduled_time = match.group(1), match.group(2)
|
||||||
time_map[username] = scheduled_time
|
time_map[username] = scheduled_time
|
||||||
@@ -81,6 +81,37 @@ def parse_time_config():
|
|||||||
print(f"❌ 解析 time.txt 失败: {e}")
|
print(f"❌ 解析 time.txt 失败: {e}")
|
||||||
return time_map
|
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():
|
def get_combined_tasks():
|
||||||
"""
|
"""
|
||||||
结合接口(is_ok==1)和本地文件(true)筛选任务
|
结合接口(is_ok==1)和本地文件(true)筛选任务
|
||||||
@@ -96,13 +127,14 @@ def get_combined_tasks():
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
task_list = {}
|
task_list = {}
|
||||||
today = datetime.now().strftime("%Y-%m-%d")
|
# today = datetime.now().strftime("%Y-%m-%d")
|
||||||
|
|
||||||
for account in accounts:
|
for account in accounts:
|
||||||
if account.get('is_ok') == 1 or account.get('username') == "czyuzongwen":
|
if account.get('is_ok') == 1:
|
||||||
user = account.get('username')
|
user = account.get('username')
|
||||||
ip = account.get('device_ip')
|
ip = account.get('device_ip')
|
||||||
port = account.get('device_port')
|
port = account.get('device_port')
|
||||||
|
project_name = account.get('project_name')
|
||||||
|
|
||||||
# 只有在 time.txt 中是 true 的账号才会被加入
|
# 只有在 time.txt 中是 true 的账号才会被加入
|
||||||
if user in local_times and ip and port:
|
if user in local_times and ip and port:
|
||||||
@@ -110,21 +142,22 @@ def get_combined_tasks():
|
|||||||
# full_time = f"{today} {local_times[user]}"
|
# full_time = f"{today} {local_times[user]}"
|
||||||
# 确保时间是两位数格式
|
# 确保时间是两位数格式
|
||||||
raw_time = local_times[user]
|
raw_time = local_times[user]
|
||||||
# 将时间格式化为两位数:9:52:20 -> 09:52:20
|
# # 将时间格式化为两位数:9:52:20 -> 09:52:20
|
||||||
if ':' in raw_time:
|
# if ':' in raw_time:
|
||||||
parts = raw_time.split(':')
|
# parts = raw_time.split(':')
|
||||||
if len(parts[0]) == 1:
|
# if len(parts[0]) == 1:
|
||||||
raw_time = f"0{raw_time}" # 补齐前导零
|
# raw_time = f"0{raw_time}" # 补齐前导零
|
||||||
|
|
||||||
full_time = f"{today} {raw_time}"
|
# full_time = f"{today} {raw_time}"
|
||||||
task_list[address] = {"time": full_time, "user": user}
|
full_time = normalize_datetime(raw_time)
|
||||||
|
task_list[address] = {"time": full_time, "user": user, "project_name": project_name}
|
||||||
|
|
||||||
return task_list
|
return task_list
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"❌ 获取任务异常: {e}")
|
print(f"❌ 获取任务异常: {e}")
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def run_task(address, target_time, username):
|
def run_task(address, target_time, username, project_name):
|
||||||
"""
|
"""
|
||||||
单个执行线程:锁定状态 -> 等待 -> 执行 -> 完成
|
单个执行线程:锁定状态 -> 等待 -> 执行 -> 完成
|
||||||
"""
|
"""
|
||||||
@@ -133,7 +166,7 @@ def run_task(address, target_time, username):
|
|||||||
if not update_file_status(username, "true", "running"):
|
if not update_file_status(username, "true", "running"):
|
||||||
return f"⏭️ {username} 状态已变更,跳过执行。"
|
return f"⏭️ {username} 状态已变更,跳过执行。"
|
||||||
|
|
||||||
print(f"🚀 [任务锁定] 设备: {address} | 用户: {username} | 计划时间: {target_time}")
|
print(f"🚀 [任务锁定] 设备: {address} | 用户: {username} | 计划时间: {target_time} | 项目: {project_name}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 2. 计算并执行等待逻辑
|
# 2. 计算并执行等待逻辑
|
||||||
@@ -146,7 +179,7 @@ def run_task(address, target_time, username):
|
|||||||
|
|
||||||
# 3. 调用 main.py 中的自动化逻辑
|
# 3. 调用 main.py 中的自动化逻辑
|
||||||
print(f"▶️ [正在执行] {username} 开始自动化操作...")
|
print(f"▶️ [正在执行] {username} 开始自动化操作...")
|
||||||
automation = DeviceAutomation(address)
|
automation = DeviceAutomation(address, project_name)
|
||||||
result = automation.handle_app_state()
|
result = automation.handle_app_state()
|
||||||
|
|
||||||
# 4. 执行完成后,将状态从 running 改为 done
|
# 4. 执行完成后,将状态从 running 改为 done
|
||||||
@@ -169,9 +202,9 @@ def monitor_center():
|
|||||||
if tasks:
|
if tasks:
|
||||||
print(f"📡 发现 {len(tasks)} 个符合条件且未跑过的任务,准备启动线程池...")
|
print(f"📡 发现 {len(tasks)} 个符合条件且未跑过的任务,准备启动线程池...")
|
||||||
with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
|
with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
|
||||||
# 提交任务,将 address, time, username 传入
|
# 提交任务,将 address, time, username, project_name 传入
|
||||||
future_to_user = {
|
future_to_user = {
|
||||||
executor.submit(run_task, addr, info['time'], info['user']): info['user']
|
executor.submit(run_task, addr, info['time'], info['user'], info.get('project_name', '')): info['user']
|
||||||
for addr, info in tasks.items()
|
for addr, info in tasks.items()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 208 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 211 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 223 KiB |
@@ -22,7 +22,7 @@ exe = EXE(
|
|||||||
a.binaries,
|
a.binaries,
|
||||||
a.datas,
|
a.datas,
|
||||||
[],
|
[],
|
||||||
name='沉降观测自动上传',
|
name='沉降观测自动截图',
|
||||||
debug=False,
|
debug=False,
|
||||||
bootloader_ignore_signals=False,
|
bootloader_ignore_signals=False,
|
||||||
strip=False,
|
strip=False,
|
||||||
Reference in New Issue
Block a user