mirror of
https://github.com/KenanZhu/AutoLibrary.git
synced 2026-06-18 07:23:03 +08:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3963b3f2e6 | |||
| f2a05809bd | |||
| b55a0c06a5 | |||
| 2496c4e367 | |||
| de30559af1 | |||
| e1c2efc8c0 | |||
| 26a70cdceb | |||
| ce14be2555 | |||
| eda16f01f1 | |||
| 22f806bfb0 | |||
| d26852eaaf | |||
| 2ffe620532 | |||
| fe42d3cd98 | |||
| 0795939aa3 | |||
| 8b6baf9b6a | |||
| 7098d7075f | |||
| be3942ea2f | |||
| 7e3a089e21 | |||
| f3d68c40cb | |||
| 0ceff677e4 | |||
| 6f6b415bff | |||
| 735f31830d | |||
| 7be5afeae1 | |||
| 3d6978c9c2 |
+14
-14
@@ -94,13 +94,13 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path "model")) {
|
if (-not (Test-Path "models")) {
|
||||||
New-Item -ItemType Directory -Path "model" | Out-Null
|
New-Item -ItemType Directory -Path "models" | Out-Null
|
||||||
Write-Host "✓ Created model directory"
|
Write-Host "✓ Created models directory"
|
||||||
}
|
}
|
||||||
|
|
||||||
$onnxSource = Join-Path $ddddocrPath "common.onnx"
|
$onnxSource = Join-Path $ddddocrPath "common.onnx"
|
||||||
$onnxDest = "model/common.onnx"
|
$onnxDest = "models/common.onnx"
|
||||||
if (Test-Path $onnxSource) {
|
if (Test-Path $onnxSource) {
|
||||||
Copy-Item $onnxSource $onnxDest -Force
|
Copy-Item $onnxSource $onnxDest -Force
|
||||||
Write-Host "✓ Copied ONNX model from: $onnxSource"
|
Write-Host "✓ Copied ONNX model from: $onnxSource"
|
||||||
@@ -119,18 +119,18 @@ jobs:
|
|||||||
}
|
}
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
|
|
||||||
- name: Compile Qt UI files
|
|
||||||
run: |
|
|
||||||
cd src/gui/batchs
|
|
||||||
./compile_ui.bat
|
|
||||||
shell: cmd
|
|
||||||
|
|
||||||
- name: Compile Qt Resource files
|
- name: Compile Qt Resource files
|
||||||
run: |
|
run: |
|
||||||
cd src/gui/batchs
|
cd batchs
|
||||||
./compile_rc.bat
|
./compile_rc.bat
|
||||||
shell: cmd
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Compile Qt UI files
|
||||||
|
run: |
|
||||||
|
cd batchs
|
||||||
|
./compile_ui.bat
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
- name: Generate 'Main.spec'
|
- name: Generate 'Main.spec'
|
||||||
run: |
|
run: |
|
||||||
$version = "${{ steps.get_version.outputs.VERSION }}"
|
$version = "${{ steps.get_version.outputs.VERSION }}"
|
||||||
@@ -148,8 +148,8 @@ jobs:
|
|||||||
" pathex=[],"
|
" pathex=[],"
|
||||||
" binaries=[],"
|
" binaries=[],"
|
||||||
" datas=["
|
" datas=["
|
||||||
" ('model\\common.onnx', 'ddddocr'),"
|
" ('models\\common.onnx', 'ddddocr'),"
|
||||||
" ('src\\gui\\icons\\AutoLibrary_32x32.ico', 'gui\\icons'),"
|
" ('src\\gui\\resources\\icons\\AutoLibrary_32x32.ico', 'gui\\resources\\icons'),"
|
||||||
" ],"
|
" ],"
|
||||||
" hiddenimports=[],"
|
" hiddenimports=[],"
|
||||||
" hookspath=[],"
|
" hookspath=[],"
|
||||||
@@ -180,7 +180,7 @@ jobs:
|
|||||||
" target_arch=None,"
|
" target_arch=None,"
|
||||||
" codesign_identity=None,"
|
" codesign_identity=None,"
|
||||||
" entitlements_file=None,"
|
" entitlements_file=None,"
|
||||||
" icon=['src\\gui\\icons\\AutoLibrary_32x32.ico'],"
|
" icon=['src\\gui\\resources\\icons\\AutoLibrary_32x32.ico'],"
|
||||||
")"
|
")"
|
||||||
)
|
)
|
||||||
$specLines | Out-File -FilePath "Main.spec" -Encoding UTF8
|
$specLines | Out-File -FilePath "Main.spec" -Encoding UTF8
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ jobs:
|
|||||||
4. 运行 `AutoLibrary-${{ needs.build.outputs.version }}.exe` (首次运行会初始化配置文件)
|
4. 运行 `AutoLibrary-${{ needs.build.outputs.version }}.exe` (首次运行会初始化配置文件)
|
||||||
5. 按照提示操作即可
|
5. 按照提示操作即可
|
||||||
|
|
||||||
更多详情请访问 [AutoLibrary 网站](http://autolibrary.cv) 和查看 [帮助手册](https://autolibrary.cv/docs/manual_lists.html)
|
更多详情请访问 [AutoLibrary 网站](http://www.autolibrary.top) 和查看 [帮助手册](https://www.autolibrary.top/manuals)
|
||||||
|
|
||||||
---
|
---
|
||||||
**完整更新日志见下方自动生成的 Release Notes**
|
**完整更新日志见下方自动生成的 Release Notes**
|
||||||
|
|||||||
+11
-11
@@ -6,16 +6,16 @@
|
|||||||
__pycache__/
|
__pycache__/
|
||||||
build/
|
build/
|
||||||
dist/
|
dist/
|
||||||
model/*.onnx
|
|
||||||
driver/*.exe
|
models/*.*
|
||||||
src/gui/configs/*.json
|
drivers/*.*
|
||||||
src/gui/translators/qtbase_zh_CN.qm
|
!models/*.md
|
||||||
src/gui/AutoLibraryResources.py
|
!drivers/*.md
|
||||||
src/gui/AutoLibraryResource.py
|
!templates/*.md
|
||||||
src/gui/Ui_ALMainWindow.py
|
!templates/configs/*.md
|
||||||
src/gui/Ui_ALConfigWidget.py
|
|
||||||
src/gui/Ui_ALTimerTaskWidget.py
|
src/gui/resources/ui/Ui_*.py
|
||||||
src/gui/Ui_ALAddTimerTaskDialog.py
|
src/gui/resources/translators/qtbase_zh_CN.qm
|
||||||
src/gui/Ui_ALAboutDialog.py
|
src/gui/resources/ALResource.py
|
||||||
|
|
||||||
Main.spec
|
Main.spec
|
||||||
@@ -3,6 +3,7 @@ chcp 65001 >nul
|
|||||||
setlocal enabledelayedexpansion
|
setlocal enabledelayedexpansion
|
||||||
|
|
||||||
cd /d "%~dp0.."
|
cd /d "%~dp0.."
|
||||||
|
cd src/gui/resources
|
||||||
|
|
||||||
echo [AutoLibrary compile] 检查翻译文件...
|
echo [AutoLibrary compile] 检查翻译文件...
|
||||||
if exist translators (
|
if exist translators (
|
||||||
@@ -18,12 +19,11 @@ if exist translators (
|
|||||||
|
|
||||||
pyside6-lrelease "%%f"
|
pyside6-lrelease "%%f"
|
||||||
if !errorlevel! equ 0 (
|
if !errorlevel! equ 0 (
|
||||||
echo [AutoLibrary compile] 翻译文件 "%%f" ✓ 编译成功,输出文件: "!qm_filename!"
|
echo [AutoLibrary compile] 翻译文件 "%%f" 编译成功,输出文件: "!qm_filename!"
|
||||||
) else (
|
) else (
|
||||||
echo [AutoLibrary compile] 翻译文件 "%%f" ✗ 编译失败
|
echo [AutoLibrary compile] 翻译文件 "%%f" 编译失败
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
echo.
|
|
||||||
) else (
|
) else (
|
||||||
echo [AutoLibrary compile] 未找到任何 .ts 翻译文件
|
echo [AutoLibrary compile] 未找到任何 .ts 翻译文件
|
||||||
)
|
)
|
||||||
@@ -52,11 +52,10 @@ for %%f in (*.qrc) do (
|
|||||||
|
|
||||||
pyside6-rcc "%%f" -o "!output_file!"
|
pyside6-rcc "%%f" -o "!output_file!"
|
||||||
if !errorlevel! equ 0 (
|
if !errorlevel! equ 0 (
|
||||||
echo [AutoLibrary compile] 文件 "%%f" ✓ 编译成功,输出文件: "!output_file!"
|
echo [AutoLibrary compile] 文件 "%%f" 编译成功,输出文件: "!output_file!"
|
||||||
) else (
|
) else (
|
||||||
echo [AutoLibrary compile] 文件 "%%f" ✗ 编译失败
|
echo [AutoLibrary compile] 文件 "%%f" 编译失败
|
||||||
)
|
)
|
||||||
echo.
|
|
||||||
)
|
)
|
||||||
|
|
||||||
echo [AutoLibrary compile] 所有操作完成。
|
echo [AutoLibrary compile] 所有操作完成。
|
||||||
Regular → Executable
+7
-11
@@ -1,8 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
PARENT_DIR="$(dirname "$SCRIPT_DIR")"
|
PRJECT_DIR="$SCRIPT_DIR/.."
|
||||||
cd "$PARENT_DIR"
|
|
||||||
|
cd "$PRJECT_DIR/src/gui/resources"
|
||||||
|
|
||||||
echo "[AutoLibrary compile] 检查翻译文件..."
|
echo "[AutoLibrary compile] 检查翻译文件..."
|
||||||
if [ -d "translators" ]; then
|
if [ -d "translators" ]; then
|
||||||
@@ -10,7 +11,6 @@ if [ -d "translators" ]; then
|
|||||||
ts_files=(*.ts)
|
ts_files=(*.ts)
|
||||||
ts_count=${#ts_files[@]}
|
ts_count=${#ts_files[@]}
|
||||||
|
|
||||||
# 如果第一个元素是"*.ts"(表示没有匹配),则数量为0
|
|
||||||
if [ "$ts_count" -eq 1 ] && [ "${ts_files[0]}" = "*.ts" ]; then
|
if [ "$ts_count" -eq 1 ] && [ "${ts_files[0]}" = "*.ts" ]; then
|
||||||
ts_count=0
|
ts_count=0
|
||||||
fi
|
fi
|
||||||
@@ -23,12 +23,11 @@ if [ -d "translators" ]; then
|
|||||||
echo "[AutoLibrary compile] 正在编译翻译文件: \"$file\" -> \"$qm_file\""
|
echo "[AutoLibrary compile] 正在编译翻译文件: \"$file\" -> \"$qm_file\""
|
||||||
|
|
||||||
if pyside6-lrelease "$file"; then
|
if pyside6-lrelease "$file"; then
|
||||||
echo "[AutoLibrary compile] 翻译文件 \"$file\" ✓ 编译成功,输出文件: \"$qm_file\""
|
echo "[AutoLibrary compile] 翻译文件 \"$file\" 编译成功,输出文件: \"$qm_file\""
|
||||||
else
|
else
|
||||||
echo "[AutoLibrary compile] 翻译文件 \"$file\" ✗ 编译失败"
|
echo "[AutoLibrary compile] 翻译文件 \"$file\" 编译失败"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
echo
|
|
||||||
else
|
else
|
||||||
echo "[AutoLibrary compile] 未找到任何 .ts 翻译文件"
|
echo "[AutoLibrary compile] 未找到任何 .ts 翻译文件"
|
||||||
fi
|
fi
|
||||||
@@ -36,7 +35,6 @@ if [ -d "translators" ]; then
|
|||||||
else
|
else
|
||||||
echo "[AutoLibrary compile] 未找到 translators 目录"
|
echo "[AutoLibrary compile] 未找到 translators 目录"
|
||||||
fi
|
fi
|
||||||
echo
|
|
||||||
|
|
||||||
file_count=$(ls *.qrc 2>/dev/null | wc -l)
|
file_count=$(ls *.qrc 2>/dev/null | wc -l)
|
||||||
|
|
||||||
@@ -46,7 +44,6 @@ if [ $file_count -eq 0 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "[AutoLibrary compile] 找到 $file_count 个 .qrc 文件,开始编译..."
|
echo "[AutoLibrary compile] 找到 $file_count 个 .qrc 文件,开始编译..."
|
||||||
echo
|
|
||||||
|
|
||||||
for file in *.qrc; do
|
for file in *.qrc; do
|
||||||
base_name=$(basename "$file" .qrc)
|
base_name=$(basename "$file" .qrc)
|
||||||
@@ -54,11 +51,10 @@ for file in *.qrc; do
|
|||||||
echo "[AutoLibrary compile] 正在编译: \"$file\" -> \"$output_file\""
|
echo "[AutoLibrary compile] 正在编译: \"$file\" -> \"$output_file\""
|
||||||
|
|
||||||
if pyside6-rcc "$file" -o "$output_file"; then
|
if pyside6-rcc "$file" -o "$output_file"; then
|
||||||
echo "[AutoLibrary compile] 文件 \"$file\" ✓ 编译成功,输出文件: \"$output_file\""
|
echo "[AutoLibrary compile] 文件 \"$file\" 编译成功,输出文件: \"$output_file\""
|
||||||
else
|
else
|
||||||
echo "[AutoLibrary compile] 文件 \"$file\" ✗ 编译失败"
|
echo "[AutoLibrary compile] 文件 \"$file\" 编译失败"
|
||||||
fi
|
fi
|
||||||
echo
|
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "[AutoLibrary compile] 所有操作完成。"
|
echo "[AutoLibrary compile] 所有操作完成。"
|
||||||
@@ -3,6 +3,7 @@ chcp 65001 >nul
|
|||||||
setlocal enabledelayedexpansion
|
setlocal enabledelayedexpansion
|
||||||
|
|
||||||
cd /d "%~dp0.."
|
cd /d "%~dp0.."
|
||||||
|
cd src/gui/resources/ui
|
||||||
|
|
||||||
set count=0
|
set count=0
|
||||||
for %%f in (*.ui) do set /a count+=1
|
for %%f in (*.ui) do set /a count+=1
|
||||||
@@ -23,11 +24,10 @@ for %%f in (*.ui) do (
|
|||||||
|
|
||||||
pyside6-uic "%%f" -o "!output_file!"
|
pyside6-uic "%%f" -o "!output_file!"
|
||||||
if !errorlevel! equ 0 (
|
if !errorlevel! equ 0 (
|
||||||
echo [AutoLibrary compile] 文件 "%%f" ✓ 编译成功,输出文件: "!output_file!"
|
echo [AutoLibrary compile] 文件 "%%f" 编译成功,输出文件: "!output_file!"
|
||||||
) else (
|
) else (
|
||||||
echo [AutoLibrary compile] 文件 "%%f" ✗ 编译失败
|
echo [AutoLibrary compile] 文件 "%%f" 编译失败
|
||||||
)
|
)
|
||||||
echo.
|
|
||||||
)
|
)
|
||||||
|
|
||||||
echo [AutoLibrary compile] 所有操作完成。
|
echo [AutoLibrary compile] 所有操作完成。
|
||||||
Regular → Executable
+5
-6
@@ -1,8 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
PARENT_DIR="$(dirname "$SCRIPT_DIR")"
|
PRJECT_DIR="$SCRIPT_DIR/.."
|
||||||
cd "$PARENT_DIR"
|
|
||||||
|
cd "$PRJECT_DIR/src/gui/resources/ui"
|
||||||
|
|
||||||
file_count=$(ls *.ui 2>/dev/null | wc -l)
|
file_count=$(ls *.ui 2>/dev/null | wc -l)
|
||||||
|
|
||||||
@@ -12,7 +13,6 @@ if [ $file_count -eq 0 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "[AutoLibrary compile] 找到 $file_count 个 .ui 文件,开始编译..."
|
echo "[AutoLibrary compile] 找到 $file_count 个 .ui 文件,开始编译..."
|
||||||
echo
|
|
||||||
|
|
||||||
for file in *.ui; do
|
for file in *.ui; do
|
||||||
base_name=$(basename "$file" .ui)
|
base_name=$(basename "$file" .ui)
|
||||||
@@ -20,11 +20,10 @@ for file in *.ui; do
|
|||||||
echo "[AutoLibrary compile] 正在编译: \"$file\" -> \"$output_file\""
|
echo "[AutoLibrary compile] 正在编译: \"$file\" -> \"$output_file\""
|
||||||
|
|
||||||
if pyside6-uic "$file" -o "$output_file"; then
|
if pyside6-uic "$file" -o "$output_file"; then
|
||||||
echo "[AutoLibrary compile] 文件 \"$file\" ✓ 编译成功,输出文件: \"$output_file\""
|
echo "[AutoLibrary compile] 文件 \"$file\" 编译成功,输出文件: \"$output_file\""
|
||||||
else
|
else
|
||||||
echo "[AutoLibrary compile] 文件 \"$file\" ✗ 编译失败"
|
echo "[AutoLibrary compile] 文件 \"$file\" 编译失败"
|
||||||
fi
|
fi
|
||||||
echo
|
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "[AutoLibrary compile] 所有操作完成。"
|
echo "[AutoLibrary compile] 所有操作完成。"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
This folder is used to store the batch scripts.
|
||||||
@@ -1 +0,0 @@
|
|||||||
For more infomation, please visit our website: https://www.autolibrary.cv
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
This folder is used to store the browser driver using by selenium.
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
This folder is used to store the browser drivers using by selenium.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
This folder is used to store the manuals.
|
||||||
|
|
||||||
|
Our manuals are available at https://www.autolibrary.top/manuals
|
||||||
@@ -1 +0,0 @@
|
|||||||
This folder is used to store the model using by ddddocr.
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
This folder is used to store the models using by ddddocr.
|
||||||
@@ -2,14 +2,15 @@
|
|||||||
# AutoLibrary
|
# AutoLibrary
|
||||||
---
|
---
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
[](https://github.com/KenanZhu/AutoLibrary)
|
||||||

|

|
||||||

|
[](https://github.com/KenanZhu/AutoLibrary/actions/workflows/release.yml)
|
||||||

|
[](https://github.com/KenanZhu/AutoLibrary/releases)
|
||||||

|

|
||||||
|
|
||||||
了解更多请访问 [_AutoLibrary 网站_](http://autolibrary.cv)
|
了解更多请访问 [_AutoLibrary 网站_](http://www.autolibrary.top)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -21,26 +22,7 @@
|
|||||||
4. 批量操作 - 支持同时预约多个用户,可以指定当前需要跳过的用户,并将用户分成多个组
|
4. 批量操作 - 支持同时预约多个用户,可以指定当前需要跳过的用户,并将用户分成多个组
|
||||||
5. 定时任务 - 使用内置定时任务管理,添加定时任务,指定时间后按当前预约信息自动运行
|
5. 定时任务 - 使用内置定时任务管理,添加定时任务,指定时间后按当前预约信息自动运行
|
||||||
|
|
||||||
*1,2,3 的具体操作方法和注意事项请访问我们的 [帮助手册](https://autolibrary.cv/docs/manual_lists.html)*
|
*1,2,3 的具体操作方法和注意事项请访问我们的 [帮助手册](https://www.autolibrary.top/manuals)*
|
||||||
|
|
||||||
### 特点
|
|
||||||
|
|
||||||
#### 关于预约等操作的注意事项
|
|
||||||
|
|
||||||
工具会自动处理登录过程的验证码识别过程,正常情况下单次识别准确率在 90% 以上,如遇验证码识别错误,大概率是校园网网络环境不佳导致的。
|
|
||||||
|
|
||||||
只要确保处于校园网网络环境内,工具都是可以正常运行的。操作处理速度基本上取决于校园网的网络环境,一般情况下在 3-4 秒(不考虑硬件差异)左右即可完成一个用户的操作,完全满足正常使用需求。
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> 工具仅作为正常的预约,签到和续约的图书馆辅助工具,请勿干扰图书馆的正常运行(如故意预约多个座位,或同时预约大量的用户等,对此影响图书馆正常运行本工具概不负责,请在善用工具方便自己的情况下尽量不用影响其他同学的使用)。
|
|
||||||
|
|
||||||
#### 关于批量操作的注意事项
|
|
||||||
|
|
||||||
批量操作时,建议将需要操作的用户分成多个组,每个组的用户数量不要超过 4 人(即一整张桌子的数量),否则会影响操作效率,大量用户同时预约会一定程度上增加图书馆服务器的压力,影响正常使用。根据需要在用户管理界面中可以勾选本次操作是否跳过该用户,以提高运行效率。
|
|
||||||
|
|
||||||
#### 关于定时任务的注意事项
|
|
||||||
|
|
||||||
定时任务会在指定的时间自动运行,运行时会根据当前预约信息进行操作。一般情况下不建议设置两个运行开始时间比较接近的定时任务,否则后一个任务会等待前一个任务完成后才会运行,按照队列的顺序执行。
|
|
||||||
|
|
||||||
### 如何使用
|
### 如何使用
|
||||||
|
|
||||||
@@ -50,7 +32,7 @@
|
|||||||
4. 运行 `AutoLibrary.exe` 文件。
|
4. 运行 `AutoLibrary.exe` 文件。
|
||||||
5. 按照提示操作即可。
|
5. 按照提示操作即可。
|
||||||
|
|
||||||
*注意 1*: 关于浏览器驱动的下载和其它相关问题,请参考我们的 [帮助手册](https://autolibrary.cv/docs/manual_lists.html) 中对应软件版本的内容。
|
*注意 1*: 关于浏览器驱动的下载和其它相关问题,请参考我们的 [帮助手册](https://www.autolibrary.top/manuals) 中对应软件版本的内容。
|
||||||
|
|
||||||
#### 平台支持 & 编译步骤
|
#### 平台支持 & 编译步骤
|
||||||
|
|
||||||
@@ -58,7 +40,7 @@
|
|||||||
|
|
||||||
1. 确保系统安装了 Python 3.13 版本 (推荐,过低或高版本会导致兼容问题)。
|
1. 确保系统安装了 Python 3.13 版本 (推荐,过低或高版本会导致兼容问题)。
|
||||||
2. 安装 pyside6 selenium ddddocr 库,命令为 `pip install pyside6 selenium ddddocr`。
|
2. 安装 pyside6 selenium ddddocr 库,命令为 `pip install pyside6 selenium ddddocr`。
|
||||||
3. 在 `src/gui/batchs` 目录下运行 `compile_ui.bat` (linux 和 macOS 系统使用 `compile_ui.sh`) 文件来编译 Qt 的 UI 文件。
|
3. 在 `batchs` 目录下运行 `compile_ui.bat` (linux 和 macOS 系统使用 `compile_ui.sh`) 文件来编译 Qt 的 UI 文件。
|
||||||
4. 在上一步相同目录内运行 `compile_rc.bat` (linux 和 macOS 系统使用 `compile_rc.sh`) 文件来编译 Qt 的资源文件。
|
4. 在上一步相同目录内运行 `compile_rc.bat` (linux 和 macOS 系统使用 `compile_rc.sh`) 文件来编译 Qt 的资源文件。
|
||||||
5. 待上述步骤完成后,运行 `src/Main.py` 文件即可。
|
5. 待上述步骤完成后,运行 `src/Main.py` 文件即可。
|
||||||
|
|
||||||
@@ -77,6 +59,25 @@ def classification(self, img: bytes):
|
|||||||
|
|
||||||
[1](@ref):[pillow 中已经删除或已经弃用的常量](https://pillow.ac.cn/en/stable/deprecations.html#constants)
|
[1](@ref):[pillow 中已经删除或已经弃用的常量](https://pillow.ac.cn/en/stable/deprecations.html#constants)
|
||||||
|
|
||||||
|
### 注意事项
|
||||||
|
|
||||||
|
#### 关于预约等操作
|
||||||
|
|
||||||
|
工具会自动处理登录过程的验证码识别过程,正常情况下单次识别准确率在 90% 以上,如遇验证码识别错误,大概率是校园网网络环境不佳导致的。
|
||||||
|
|
||||||
|
只要确保处于校园网网络环境内,工具都是可以正常运行的。操作处理速度基本上取决于校园网的网络环境,一般情况下在 3-4 秒(不考虑硬件差异)左右即可完成一个用户的操作,完全满足正常使用需求。
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> 工具仅作为正常的预约,签到和续约的图书馆辅助工具,请勿干扰图书馆的正常运行(如故意预约多个座位,或同时预约大量的用户等,对此影响图书馆正常运行本工具概不负责,请在善用工具方便自己的情况下尽量不用影响其他同学的使用)。
|
||||||
|
|
||||||
|
#### 关于批量操作
|
||||||
|
|
||||||
|
批量操作时,建议将需要操作的用户分成多个组,每个组的用户数量不要超过 4 人(即一整张桌子的数量),否则会影响操作效率,大量用户同时预约会一定程度上增加图书馆服务器的压力,影响正常使用。根据需要在用户管理界面中可以勾选本次操作是否跳过该用户,以提高运行效率。
|
||||||
|
|
||||||
|
#### 关于定时任务
|
||||||
|
|
||||||
|
定时任务会在指定的时间自动运行,运行时会根据当前预约信息进行操作。一般情况下不建议设置两个运行开始时间比较接近的定时任务,否则后一个任务会等待前一个任务完成后才会运行,按照队列的顺序执行。
|
||||||
|
|
||||||
### Q&A
|
### Q&A
|
||||||
|
|
||||||
#### 为什么开发这个工具?
|
#### 为什么开发这个工具?
|
||||||
@@ -97,7 +98,7 @@ def classification(self, img: bytes):
|
|||||||
|
|
||||||
#### 后续会有哪些功能?
|
#### 后续会有哪些功能?
|
||||||
|
|
||||||
当前 v1.0.0 版本的功能对于正常使用已经足够,不过后续会着重考虑完善 2-4 人预约时的使用体验,暂时有以下构想:
|
当前版本的功能对于正常使用已经足够,不过后续会着重考虑完善 2-4 人预约时的使用体验,暂时有以下构想:
|
||||||
|
|
||||||
1. 2-4 人一起预约时,往往会偏向于预约并排或对面的整个空座位,这时候工具会按照一定策略查询搜索符合条件的座位,并预约并排或对面的整个座位,而不是各自独立预约。
|
1. 2-4 人一起预约时,往往会偏向于预约并排或对面的整个空座位,这时候工具会按照一定策略查询搜索符合条件的座位,并预约并排或对面的整个座位,而不是各自独立预约。
|
||||||
2. 预约时会考虑到组内用户的预约时间是否冲突,若冲突则会提示用户是否继续预约,若用户选择继续预约,则会按需要调整预约时间,再进行预约。
|
2. 预约时会考虑到组内用户的预约时间是否冲突,若冲突则会提示用户是否继续预约,若用户选择继续预约,则会按需要调整预约时间,再进行预约。
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ from PySide6.QtCore import QTranslator
|
|||||||
from PySide6.QtWidgets import QApplication
|
from PySide6.QtWidgets import QApplication
|
||||||
|
|
||||||
from gui.ALMainWindow import ALMainWindow
|
from gui.ALMainWindow import ALMainWindow
|
||||||
from gui import AutoLibraryResource
|
from gui.resources import ALResource
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
+2
-14
@@ -7,8 +7,8 @@ This software is provided "as is", without any warranty of any kind.
|
|||||||
You may use, modify, and distribute this file under the terms of the MIT License.
|
You may use, modify, and distribute this file under the terms of the MIT License.
|
||||||
See the LICENSE file for details.
|
See the LICENSE file for details.
|
||||||
"""
|
"""
|
||||||
import time
|
|
||||||
import queue
|
import queue
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
class MsgBase:
|
class MsgBase:
|
||||||
@@ -53,7 +53,7 @@ class MsgBase:
|
|||||||
msg: str
|
msg: str
|
||||||
):
|
):
|
||||||
|
|
||||||
timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
|
||||||
self._output_queue.put(f"{timestamp}-[{self._class_name:<15}] : {msg}")
|
self._output_queue.put(f"{timestamp}-[{self._class_name:<15}] : {msg}")
|
||||||
|
|
||||||
|
|
||||||
@@ -67,15 +67,3 @@ class MsgBase:
|
|||||||
return msg
|
return msg
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _inputMsg(
|
|
||||||
self,
|
|
||||||
timeout: float = 1.0
|
|
||||||
) -> bool:
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._input_queue.get(timeout=timeout)
|
|
||||||
return True
|
|
||||||
except queue.Empty:
|
|
||||||
return False
|
|
||||||
|
|||||||
@@ -7,11 +7,10 @@ This software is provided "as is", without any warranty of any kind.
|
|||||||
You may use, modify, and distribute this file under the terms of the MIT License.
|
You may use, modify, and distribute this file under the terms of the MIT License.
|
||||||
See the LICENSE file for details.
|
See the LICENSE file for details.
|
||||||
"""
|
"""
|
||||||
import sys
|
|
||||||
import platform
|
import platform
|
||||||
|
|
||||||
from PySide6.QtGui import (
|
from PySide6.QtGui import (
|
||||||
QIcon
|
QIcon, QFont
|
||||||
)
|
)
|
||||||
from PySide6.QtWidgets import (
|
from PySide6.QtWidgets import (
|
||||||
QDialog, QApplication
|
QDialog, QApplication
|
||||||
@@ -23,9 +22,9 @@ from PySide6.QtCore import (
|
|||||||
from gui.ALVersionInfo import (
|
from gui.ALVersionInfo import (
|
||||||
AL_VERSION, AL_COMMIT_SHA, AL_COMMIT_DATE, AL_BUILD_DATE
|
AL_VERSION, AL_COMMIT_SHA, AL_COMMIT_DATE, AL_BUILD_DATE
|
||||||
)
|
)
|
||||||
from gui.Ui_ALAboutDialog import Ui_ALAboutDialog
|
from gui.resources.ui.Ui_ALAboutDialog import Ui_ALAboutDialog
|
||||||
|
|
||||||
from gui import AutoLibraryResource
|
from gui.resources import ALResource
|
||||||
|
|
||||||
|
|
||||||
class ALAboutDialog(QDialog, Ui_ALAboutDialog):
|
class ALAboutDialog(QDialog, Ui_ALAboutDialog):
|
||||||
@@ -47,8 +46,11 @@ class ALAboutDialog(QDialog, Ui_ALAboutDialog):
|
|||||||
|
|
||||||
self.LogoIconLabel.setPixmap(QIcon(":/res/icon/icons/AutoLibrary_32x32.ico").pixmap(48, 48))
|
self.LogoIconLabel.setPixmap(QIcon(":/res/icon/icons/AutoLibrary_32x32.ico").pixmap(48, 48))
|
||||||
info_text = self.generateAboutText()
|
info_text = self.generateAboutText()
|
||||||
self.AboutInfoEdit.setHtml(info_text)
|
self.AboutInfoBrowser.setHtml(info_text)
|
||||||
self.AboutInfoEdit.setTextInteractionFlags(Qt.TextBrowserInteraction)
|
browser_font = self.AboutInfoBrowser.font()
|
||||||
|
browser_font.setFamily("Courier New")
|
||||||
|
self.AboutInfoBrowser.setFont(browser_font)
|
||||||
|
self.AboutInfoBrowser.setTextInteractionFlags(Qt.TextBrowserInteraction)
|
||||||
|
|
||||||
|
|
||||||
def connectSignals(
|
def connectSignals(
|
||||||
@@ -60,7 +62,7 @@ class ALAboutDialog(QDialog, Ui_ALAboutDialog):
|
|||||||
|
|
||||||
def generateAboutText(
|
def generateAboutText(
|
||||||
self
|
self
|
||||||
):
|
) -> str:
|
||||||
|
|
||||||
os_info = self.getOSInfo()
|
os_info = self.getOSInfo()
|
||||||
about_text = f"""
|
about_text = f"""
|
||||||
@@ -81,7 +83,7 @@ System architecture: {os_info['architecture']}<br>
|
|||||||
<h4>Project Information:</h4>
|
<h4>Project Information:</h4>
|
||||||
License: MIT License<br>
|
License: MIT License<br>
|
||||||
Project repository: <a href="https://www.github.com/KenanZhu/AutoLibrary" style="text-decoration: none;">https://www.github.com/KenanZhu/AutoLibrary</a><br>
|
Project repository: <a href="https://www.github.com/KenanZhu/AutoLibrary" style="text-decoration: none;">https://www.github.com/KenanZhu/AutoLibrary</a><br>
|
||||||
Project website: <a href="https://www.autolibrary.cv/" style="text-decoration: none;">https://www.autolibrary.cv/</a><br>
|
Project website: <a href="https://www.autolibrary.top" style="text-decoration: none;">https://www.autolibrary.top</a><br>
|
||||||
|
|
||||||
<h4>Author Information:</h4>
|
<h4>Author Information:</h4>
|
||||||
Developer: KenanZhu<br>
|
Developer: KenanZhu<br>
|
||||||
@@ -138,7 +140,7 @@ GitHub: <a href="https://www.github.com/KenanZhu" style="text-decoration: none;"
|
|||||||
self
|
self
|
||||||
):
|
):
|
||||||
|
|
||||||
about_text = self.AboutInfoEdit.toPlainText()
|
about_text = self.AboutInfoBrowser.toPlainText()
|
||||||
clipboard = QApplication.clipboard()
|
clipboard = QApplication.clipboard()
|
||||||
clipboard.setText(about_text)
|
clipboard.setText(about_text)
|
||||||
original_text = self.CopyButton.text()
|
original_text = self.CopyButton.text()
|
||||||
|
|||||||
+34
-55
@@ -14,18 +14,17 @@ from PySide6.QtCore import (
|
|||||||
Qt, Signal, Slot, QTime, QDate, QDir, QFileInfo
|
Qt, Signal, Slot, QTime, QDate, QDir, QFileInfo
|
||||||
)
|
)
|
||||||
from PySide6.QtWidgets import (
|
from PySide6.QtWidgets import (
|
||||||
QWidget, QLineEdit, QMessageBox, QFileDialog,
|
QDialog, QWidget, QLineEdit, QMessageBox, QFileDialog,
|
||||||
QTreeWidgetItem, QMenu, QInputDialog
|
QTreeWidgetItem, QMenu, QInputDialog
|
||||||
)
|
)
|
||||||
from PySide6.QtGui import (
|
from PySide6.QtGui import (
|
||||||
QCloseEvent, QAction
|
QCloseEvent, QAction
|
||||||
)
|
)
|
||||||
|
|
||||||
from gui.Ui_ALConfigWidget import Ui_ALConfigWidget
|
from gui.resources.ui.Ui_ALConfigWidget import Ui_ALConfigWidget
|
||||||
from gui.ALSeatMapWidget import ALSeatMapWidget
|
from gui.ALSeatMapSelectDialog import ALSeatMapSelectDialog
|
||||||
from gui.ALSeatMapTable import seats_maps
|
from gui.ALSeatMapTable import ALSeatMapTable
|
||||||
from gui.ALUserTreeWidget import TreeItemType
|
from gui.ALUserTreeWidget import ALUserTreeWidget, ALUserTreeItemType
|
||||||
from gui.ALUserTreeWidget import ALUserTreeWidget
|
|
||||||
|
|
||||||
from utils.ConfigReader import ConfigReader
|
from utils.ConfigReader import ConfigReader
|
||||||
from utils.ConfigWriter import ConfigWriter
|
from utils.ConfigWriter import ConfigWriter
|
||||||
@@ -33,7 +32,7 @@ from utils.ConfigWriter import ConfigWriter
|
|||||||
|
|
||||||
class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
||||||
|
|
||||||
configWidgetCloseSingal = Signal(dict)
|
configWidgetIsClosed = Signal(dict)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -47,7 +46,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.__config_paths = config_paths
|
self.__config_paths = config_paths
|
||||||
self.__config_data = {"run": {}, "user": {}}
|
self.__config_data = {"run": {}, "user": {}}
|
||||||
self.__seat_map_widget = None
|
|
||||||
|
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.modifyUi()
|
self.modifyUi()
|
||||||
@@ -126,7 +124,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
event: QCloseEvent
|
event: QCloseEvent
|
||||||
):
|
):
|
||||||
|
|
||||||
self.configWidgetCloseSingal.emit(self.__config_paths)
|
self.configWidgetIsClosed.emit(self.__config_paths)
|
||||||
super().closeEvent(event)
|
super().closeEvent(event)
|
||||||
|
|
||||||
|
|
||||||
@@ -196,7 +194,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
which: str
|
which: str
|
||||||
) -> bool:
|
) -> bool:
|
||||||
|
|
||||||
msg = ""
|
msg = "" # no use for now
|
||||||
is_success = True
|
is_success = True
|
||||||
if which == "run":
|
if which == "run":
|
||||||
run_config_path = self.__config_paths[which]
|
run_config_path = self.__config_paths[which]
|
||||||
@@ -224,12 +222,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
self.__config_data[which] = self.loadUserConfig(user_config_path)
|
self.__config_data[which] = self.loadUserConfig(user_config_path)
|
||||||
if self.__config_data[which] is None:
|
if self.__config_data[which] is None:
|
||||||
is_success = False
|
is_success = False
|
||||||
if msg:
|
|
||||||
QMessageBox.information(
|
|
||||||
self,
|
|
||||||
"提示 - AutoLibrary",
|
|
||||||
f"配置文件初始化完成: \n{msg}"
|
|
||||||
)
|
|
||||||
return is_success
|
return is_success
|
||||||
|
|
||||||
|
|
||||||
@@ -625,12 +617,12 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
try:
|
try:
|
||||||
if "groups" in user_config_data:
|
if "groups" in user_config_data:
|
||||||
for group_config in user_config_data["groups"]:
|
for group_config in user_config_data["groups"]:
|
||||||
group_item = QTreeWidgetItem(self.UserTreeWidget, TreeItemType.GROUP.value)
|
group_item = QTreeWidgetItem(self.UserTreeWidget, ALUserTreeItemType.GROUP.value)
|
||||||
group_item.setText(0, group_config["name"])
|
group_item.setText(0, group_config["name"])
|
||||||
group_item.setFlags(group_item.flags() | Qt.ItemIsEditable)
|
group_item.setFlags(group_item.flags() | Qt.ItemIsEditable)
|
||||||
group_item.setCheckState(1, Qt.Checked if group_config.get("enabled", True) else Qt.Unchecked)
|
group_item.setCheckState(1, Qt.Checked if group_config.get("enabled", True) else Qt.Unchecked)
|
||||||
for user_config in group_config["users"]:
|
for user_config in group_config["users"]:
|
||||||
user_item = QTreeWidgetItem(group_item, TreeItemType.USER.value)
|
user_item = QTreeWidgetItem(group_item, ALUserTreeItemType.USER.value)
|
||||||
user_item.setText(0, user_config["username"])
|
user_item.setText(0, user_config["username"])
|
||||||
user_item.setText(1, "" if user_config.get("enabled", True) else "跳过")
|
user_item.setText(1, "" if user_config.get("enabled", True) else "跳过")
|
||||||
user_item.setData(0, Qt.UserRole, user_config)
|
user_item.setData(0, Qt.UserRole, user_config)
|
||||||
@@ -647,7 +639,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
) -> QTreeWidgetItem:
|
) -> QTreeWidgetItem:
|
||||||
|
|
||||||
self.UserTreeWidget.itemChanged.disconnect(self.onUserTreeWidgetItemChanged)
|
self.UserTreeWidget.itemChanged.disconnect(self.onUserTreeWidgetItemChanged)
|
||||||
group_item = QTreeWidgetItem(self.UserTreeWidget, TreeItemType.GROUP.value)
|
group_item = QTreeWidgetItem(self.UserTreeWidget, ALUserTreeItemType.GROUP.value)
|
||||||
if not group_name:
|
if not group_name:
|
||||||
group_name = f"新分组-{self.UserTreeWidget.topLevelItemCount()}"
|
group_name = f"新分组-{self.UserTreeWidget.topLevelItemCount()}"
|
||||||
group_item.setText(0, group_name)
|
group_item.setText(0, group_name)
|
||||||
@@ -667,7 +659,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
current_item = self.UserTreeWidget.currentItem()
|
current_item = self.UserTreeWidget.currentItem()
|
||||||
if current_item is None:
|
if current_item is None:
|
||||||
group_item = self.addGroup()
|
group_item = self.addGroup()
|
||||||
if group_item.type() == TreeItemType.USER.value:
|
if group_item.type() == ALUserTreeItemType.USER.value:
|
||||||
group_item = group_item.parent()
|
group_item = group_item.parent()
|
||||||
if group_item.checkState(1) == Qt.CheckState.Unchecked:
|
if group_item.checkState(1) == Qt.CheckState.Unchecked:
|
||||||
return None
|
return None
|
||||||
@@ -701,7 +693,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.UserTreeWidget.itemChanged.disconnect(self.onUserTreeWidgetItemChanged)
|
self.UserTreeWidget.itemChanged.disconnect(self.onUserTreeWidgetItemChanged)
|
||||||
user_item = QTreeWidgetItem(group_item, TreeItemType.USER.value)
|
user_item = QTreeWidgetItem(group_item, ALUserTreeItemType.USER.value)
|
||||||
user_item.setText(0, new_user["username"])
|
user_item.setText(0, new_user["username"])
|
||||||
user_item.setText(1, "")
|
user_item.setText(1, "")
|
||||||
user_item.setData(0, Qt.UserRole, new_user)
|
user_item.setData(0, Qt.UserRole, new_user)
|
||||||
@@ -720,7 +712,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
|
|
||||||
if user_item is None:
|
if user_item is None:
|
||||||
return
|
return
|
||||||
if user_item.type() != TreeItemType.USER.value:
|
if user_item.type() != ALUserTreeItemType.USER.value:
|
||||||
return
|
return
|
||||||
parent_item = user_item.parent()
|
parent_item = user_item.parent()
|
||||||
index = parent_item.indexOfChild(user_item)
|
index = parent_item.indexOfChild(user_item)
|
||||||
@@ -736,7 +728,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
|
|
||||||
if group_item is None:
|
if group_item is None:
|
||||||
return
|
return
|
||||||
if group_item.type() != TreeItemType.GROUP.value:
|
if group_item.type() != ALUserTreeItemType.GROUP.value:
|
||||||
return
|
return
|
||||||
index = self.UserTreeWidget.indexOfTopLevelItem(group_item)
|
index = self.UserTreeWidget.indexOfTopLevelItem(group_item)
|
||||||
self.UserTreeWidget.takeTopLevelItem(index)
|
self.UserTreeWidget.takeTopLevelItem(index)
|
||||||
@@ -761,7 +753,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
if not ok or not new_name:
|
if not ok or not new_name:
|
||||||
return
|
return
|
||||||
item.setText(0, new_name)
|
item.setText(0, new_name)
|
||||||
if item.type() == TreeItemType.GROUP.value:
|
if item.type() == ALUserTreeItemType.GROUP.value:
|
||||||
item.setText(0, new_name)
|
item.setText(0, new_name)
|
||||||
else:
|
else:
|
||||||
user = item.data(0, Qt.UserRole)
|
user = item.data(0, Qt.UserRole)
|
||||||
@@ -792,20 +784,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
self.RoomComboBox.addItems(self.__floor_room_map[floor])
|
self.RoomComboBox.addItems(self.__floor_room_map[floor])
|
||||||
self.RoomComboBox.setCurrentIndex(0)
|
self.RoomComboBox.setCurrentIndex(0)
|
||||||
|
|
||||||
@Slot()
|
|
||||||
def onSeatMapWidgetClosed(
|
|
||||||
self,
|
|
||||||
selected_seats: list[str]
|
|
||||||
):
|
|
||||||
|
|
||||||
self.__seat_map_widget.seatMapWidgetClosed.disconnect(self.onSeatMapWidgetClosed)
|
|
||||||
self.__seat_map_widget.deleteLater()
|
|
||||||
self.__seat_map_widget = None
|
|
||||||
if len(selected_seats) == 0:
|
|
||||||
self.SeatIDEdit.clear() # no selected seat, we clear the edit
|
|
||||||
return
|
|
||||||
self.SeatIDEdit.setText(",".join(selected_seats))
|
|
||||||
|
|
||||||
@Slot()
|
@Slot()
|
||||||
def onSelectSeatsButtonClicked(
|
def onSelectSeatsButtonClicked(
|
||||||
self
|
self
|
||||||
@@ -815,18 +793,19 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
room = self.RoomComboBox.currentText()
|
room = self.RoomComboBox.currentText()
|
||||||
floor_idx = self.__floor_rmap[floor]
|
floor_idx = self.__floor_rmap[floor]
|
||||||
room_idx = self.__room_rmap[room]
|
room_idx = self.__room_rmap[room]
|
||||||
if self.__seat_map_widget is None:
|
dialog = ALSeatMapSelectDialog(
|
||||||
self.__seat_map_widget = ALSeatMapWidget(
|
self,
|
||||||
self,
|
floor,
|
||||||
floor,
|
room,
|
||||||
room,
|
ALSeatMapTable[floor_idx][room_idx]
|
||||||
seats_maps[floor_idx][room_idx]
|
)
|
||||||
)
|
dialog.selectSeats(self.SeatIDEdit.text().split(","))
|
||||||
self.__seat_map_widget.seatMapWidgetClosed.connect(self.onSeatMapWidgetClosed)
|
if dialog.exec() == QDialog.DialogCode.Accepted:
|
||||||
self.__seat_map_widget.show()
|
selected_seats = dialog.getSelectedSeats()
|
||||||
self.__seat_map_widget.raise_()
|
if len(selected_seats) == 0:
|
||||||
self.__seat_map_widget.activateWindow()
|
self.SeatIDEdit.clear()
|
||||||
self.__seat_map_widget.selectSeats(self.SeatIDEdit.text().split(","))
|
return
|
||||||
|
self.SeatIDEdit.setText(",".join(dialog.getSelectedSeats()))
|
||||||
|
|
||||||
@Slot()
|
@Slot()
|
||||||
def onUserTreeWidgetCurrentItemChanged(
|
def onUserTreeWidgetCurrentItemChanged(
|
||||||
@@ -838,7 +817,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
# cant effectively update the data of each user, due to the
|
# cant effectively update the data of each user, due to the
|
||||||
# possiblity of frequency edit. we just let the QListWidget
|
# possiblity of frequency edit. we just let the QListWidget
|
||||||
# help us.
|
# help us.
|
||||||
if previous and previous.type() == TreeItemType.USER.value:
|
if previous and previous.type() == ALUserTreeItemType.USER.value:
|
||||||
user = self.collectUserFromUserInfoWidget()
|
user = self.collectUserFromUserInfoWidget()
|
||||||
if user:
|
if user:
|
||||||
self.UsernameEdit.textEdited.disconnect()
|
self.UsernameEdit.textEdited.disconnect()
|
||||||
@@ -849,7 +828,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
if current is None:
|
if current is None:
|
||||||
self.initilizeUserInfoWidget()
|
self.initilizeUserInfoWidget()
|
||||||
return
|
return
|
||||||
if current.type() == TreeItemType.USER.value:
|
if current.type() == ALUserTreeItemType.USER.value:
|
||||||
user = current.data(0, Qt.UserRole)
|
user = current.data(0, Qt.UserRole)
|
||||||
if user:
|
if user:
|
||||||
self.setUserToWidget(user)
|
self.setUserToWidget(user)
|
||||||
@@ -868,7 +847,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
return
|
return
|
||||||
if column != 1:
|
if column != 1:
|
||||||
return
|
return
|
||||||
if item.type() == TreeItemType.GROUP.value:
|
if item.type() == ALUserTreeItemType.GROUP.value:
|
||||||
is_checked = item.checkState(1) == Qt.CheckState.Checked
|
is_checked = item.checkState(1) == Qt.CheckState.Checked
|
||||||
for i in range(item.childCount()):
|
for i in range(item.childCount()):
|
||||||
child = item.child(i)
|
child = item.child(i)
|
||||||
@@ -933,7 +912,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
menu = QMenu(self.UserTreeWidget)
|
menu = QMenu(self.UserTreeWidget)
|
||||||
if current_item is None:
|
if current_item is None:
|
||||||
self.showTreeMenu(menu)
|
self.showTreeMenu(menu)
|
||||||
elif current_item.type() == TreeItemType.GROUP.value:
|
elif current_item.type() == ALUserTreeItemType.GROUP.value:
|
||||||
self.showGroupMenu(menu, current_item)
|
self.showGroupMenu(menu, current_item)
|
||||||
else:
|
else:
|
||||||
self.showUserMenu(menu, current_item)
|
self.showUserMenu(menu, current_item)
|
||||||
@@ -1115,7 +1094,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
|||||||
):
|
):
|
||||||
|
|
||||||
current_item = self.UserTreeWidget.currentItem()
|
current_item = self.UserTreeWidget.currentItem()
|
||||||
if current_item and current_item.type() == TreeItemType.USER.value:
|
if current_item and current_item.type() == ALUserTreeItemType.USER.value:
|
||||||
self.UserTreeWidget.setCurrentItem(None)
|
self.UserTreeWidget.setCurrentItem(None)
|
||||||
if self.saveConfigs(
|
if self.saveConfigs(
|
||||||
self.__config_paths["run"],
|
self.__config_paths["run"],
|
||||||
|
|||||||
+30
-47
@@ -21,16 +21,18 @@ from PySide6.QtGui import (
|
|||||||
QTextCursor, QCloseEvent, QFont, QIcon, QDesktopServices
|
QTextCursor, QCloseEvent, QFont, QIcon, QDesktopServices
|
||||||
)
|
)
|
||||||
|
|
||||||
from gui.Ui_ALMainWindow import Ui_ALMainWindow
|
from base.MsgBase import MsgBase
|
||||||
|
|
||||||
|
from gui.resources.ui.Ui_ALMainWindow import Ui_ALMainWindow
|
||||||
from gui.ALConfigWidget import ALConfigWidget
|
from gui.ALConfigWidget import ALConfigWidget
|
||||||
from gui.ALTimerTaskWidget import ALTimerTaskWidget
|
from gui.ALTimerTaskManageWidget import ALTimerTaskManageWidget
|
||||||
from gui.ALAboutDialog import ALAboutDialog
|
from gui.ALAboutDialog import ALAboutDialog
|
||||||
from gui.ALMainWorkers import TimerTaskWorker, AutoLibWorker
|
from gui.ALMainWorkers import TimerTaskWorker, AutoLibWorker
|
||||||
|
|
||||||
from gui import AutoLibraryResource
|
from gui.resources import ALResource
|
||||||
|
|
||||||
|
|
||||||
class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
|
||||||
|
|
||||||
timerTaskIsRunning = Signal(dict)
|
timerTaskIsRunning = Signal(dict)
|
||||||
timerTaskIsExecuted = Signal(dict)
|
timerTaskIsExecuted = Signal(dict)
|
||||||
@@ -40,10 +42,8 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
self
|
self
|
||||||
):
|
):
|
||||||
|
|
||||||
super().__init__()
|
MsgBase.__init__(self, queue.Queue(), queue.Queue())
|
||||||
self.__class_name = self.__class__.__name__
|
QMainWindow.__init__(self)
|
||||||
self.__input_queue = queue.Queue()
|
|
||||||
self.__output_queue = queue.Queue()
|
|
||||||
self.__timer_task_queue = queue.Queue()
|
self.__timer_task_queue = queue.Queue()
|
||||||
script_path = sys.executable
|
script_path = sys.executable
|
||||||
script_dir = QFileInfo(script_path).absoluteDir()
|
script_dir = QFileInfo(script_path).absoluteDir()
|
||||||
@@ -77,12 +77,12 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
self.AboutAction.triggered.connect(self.onAboutActionTriggered)
|
self.AboutAction.triggered.connect(self.onAboutActionTriggered)
|
||||||
|
|
||||||
# initialize timer task widget, but not show it
|
# initialize timer task widget, but not show it
|
||||||
self.__alTimerTaskWidget = ALTimerTaskWidget(self, self.__config_paths["timer_task"])
|
self.__alTimerTaskWidget = ALTimerTaskManageWidget(self, self.__config_paths["timer_task"])
|
||||||
self.timerTaskIsRunning.connect(self.__alTimerTaskWidget.onTimerTaskIsRunning)
|
self.timerTaskIsRunning.connect(self.__alTimerTaskWidget.onTimerTaskIsRunning)
|
||||||
self.timerTaskIsExecuted.connect(self.__alTimerTaskWidget.onTimerTaskIsExecuted)
|
self.timerTaskIsExecuted.connect(self.__alTimerTaskWidget.onTimerTaskIsExecuted)
|
||||||
self.timerTaskIsError.connect(self.__alTimerTaskWidget.onTimerTaskIsError)
|
self.timerTaskIsError.connect(self.__alTimerTaskWidget.onTimerTaskIsError)
|
||||||
self.__alTimerTaskWidget.timerTaskIsReady.connect(self.onTimerTaskIsReady)
|
self.__alTimerTaskWidget.timerTaskIsReady.connect(self.onTimerTaskIsReady)
|
||||||
self.__alTimerTaskWidget.timerTaskWidgetClosed.connect(self.onTimerTaskWidgetClosed)
|
self.__alTimerTaskWidget.timerTaskManageWidgetClosed.connect(self.onTimerTaskWidgetClosed)
|
||||||
self.__alTimerTaskWidget.setWindowFlags(Qt.WindowType.Window|Qt.WindowType.WindowCloseButtonHint)
|
self.__alTimerTaskWidget.setWindowFlags(Qt.WindowType.Window|Qt.WindowType.WindowCloseButtonHint)
|
||||||
|
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
self
|
self
|
||||||
):
|
):
|
||||||
|
|
||||||
url = QUrl("https://www.autolibrary.cv/docs/manual_lists.html")
|
url = QUrl("https://www.autolibrary.top/manuals")
|
||||||
QDesktopServices.openUrl(url)
|
QDesktopServices.openUrl(url)
|
||||||
|
|
||||||
|
|
||||||
@@ -226,7 +226,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
self.timerTaskIsRunning.emit(timer_task)
|
self.timerTaskIsRunning.emit(timer_task)
|
||||||
self.__timer_task_timer.stop()
|
self.__timer_task_timer.stop()
|
||||||
self.__is_running_timer_task = True
|
self.__is_running_timer_task = True
|
||||||
self.setControlButtons(True, True, False)
|
self.setControlButtons(None, True, False)
|
||||||
if not timer_task["silent"]:
|
if not timer_task["silent"]:
|
||||||
self.TrayIcon.showMessage(
|
self.TrayIcon.showMessage(
|
||||||
"定时任务 - AutoLibrary",
|
"定时任务 - AutoLibrary",
|
||||||
@@ -237,11 +237,11 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
self.showNormal()
|
self.showNormal()
|
||||||
self.__current_timer_task_thread = TimerTaskWorker(
|
self.__current_timer_task_thread = TimerTaskWorker(
|
||||||
timer_task,
|
timer_task,
|
||||||
self.__input_queue,
|
self._input_queue,
|
||||||
self.__output_queue,
|
self._output_queue,
|
||||||
self.__config_paths
|
self.__config_paths
|
||||||
)
|
)
|
||||||
self.__current_timer_task_thread.finishedSignal_TimerWorker.connect(self.onTimerTaskFinished)
|
self.__current_timer_task_thread.TimerTaskWorkerIsFinished.connect(self.onTimerTaskFinished)
|
||||||
self.__current_timer_task_thread.start()
|
self.__current_timer_task_thread.start()
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
self.__is_running_timer_task = False
|
self.__is_running_timer_task = False
|
||||||
@@ -263,23 +263,6 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
if start_button_enabled is not None:
|
if start_button_enabled is not None:
|
||||||
self.StartButton.setEnabled(start_button_enabled)
|
self.StartButton.setEnabled(start_button_enabled)
|
||||||
|
|
||||||
@Slot()
|
|
||||||
def showMsg(
|
|
||||||
self,
|
|
||||||
msg: str
|
|
||||||
):
|
|
||||||
|
|
||||||
self.__output_queue.put(f"[{self.__class_name:<15}] >>> : {msg}")
|
|
||||||
|
|
||||||
@Slot()
|
|
||||||
def showTrace(
|
|
||||||
self,
|
|
||||||
msg: str
|
|
||||||
):
|
|
||||||
|
|
||||||
timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
|
||||||
self.__output_queue.put(f"{timestamp}-[{self.__class_name:<15}] : {msg}")
|
|
||||||
|
|
||||||
@Slot()
|
@Slot()
|
||||||
def pollMsgQueue(
|
def pollMsgQueue(
|
||||||
self
|
self
|
||||||
@@ -287,7 +270,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
msg = self.__output_queue.get_nowait()
|
msg = self._output_queue.get_nowait()
|
||||||
self.appendToTextEdit(msg)
|
self.appendToTextEdit(msg)
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
pass
|
pass
|
||||||
@@ -306,7 +289,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
):
|
):
|
||||||
|
|
||||||
if self.__alConfigWidget:
|
if self.__alConfigWidget:
|
||||||
self.__alConfigWidget.configWidgetCloseSingal.disconnect(self.onConfigWidgetClosed)
|
self.__alConfigWidget.configWidgetIsClosed.disconnect(self.onConfigWidgetClosed)
|
||||||
self.__alConfigWidget.deleteLater()
|
self.__alConfigWidget.deleteLater()
|
||||||
self.__alConfigWidget = None
|
self.__alConfigWidget = None
|
||||||
self.setControlButtons(True, None, None)
|
self.setControlButtons(True, None, None)
|
||||||
@@ -328,7 +311,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
):
|
):
|
||||||
|
|
||||||
self.__current_timer_task_thread.wait(1000)
|
self.__current_timer_task_thread.wait(1000)
|
||||||
self.__current_timer_task_thread.finishedSignal_TimerWorker.disconnect(self.onTimerTaskFinished)
|
self.__current_timer_task_thread.TimerTaskWorkerIsFinished.disconnect(self.onTimerTaskFinished)
|
||||||
self.__current_timer_task_thread.deleteLater()
|
self.__current_timer_task_thread.deleteLater()
|
||||||
self.__current_timer_task_thread = None
|
self.__current_timer_task_thread = None
|
||||||
self.setControlButtons(None, False, True)
|
self.setControlButtons(None, False, True)
|
||||||
@@ -341,7 +324,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
QSystemTrayIcon.MessageIcon.Information,
|
QSystemTrayIcon.MessageIcon.Information,
|
||||||
1000
|
1000
|
||||||
)
|
)
|
||||||
self.showTrace(
|
self._showTrace(
|
||||||
f"定时任务 {timer_task['name']} 执行{'失败' if is_error else '完成'}, uuid: {timer_task['task_uuid']}"
|
f"定时任务 {timer_task['name']} 执行{'失败' if is_error else '完成'}, uuid: {timer_task['task_uuid']}"
|
||||||
)
|
)
|
||||||
if not is_error:
|
if not is_error:
|
||||||
@@ -369,7 +352,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
self,
|
self,
|
||||||
self.__config_paths
|
self.__config_paths
|
||||||
)
|
)
|
||||||
self.__alConfigWidget.configWidgetCloseSingal.connect(self.onConfigWidgetClosed)
|
self.__alConfigWidget.configWidgetIsClosed.connect(self.onConfigWidgetClosed)
|
||||||
self.__alConfigWidget.show()
|
self.__alConfigWidget.show()
|
||||||
self.__alConfigWidget.raise_()
|
self.__alConfigWidget.raise_()
|
||||||
self.__alConfigWidget.activateWindow()
|
self.__alConfigWidget.activateWindow()
|
||||||
@@ -383,12 +366,12 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
self.setControlButtons(None, True, False)
|
self.setControlButtons(None, True, False)
|
||||||
if self.__auto_lib_thread is None:
|
if self.__auto_lib_thread is None:
|
||||||
self.__auto_lib_thread = AutoLibWorker(
|
self.__auto_lib_thread = AutoLibWorker(
|
||||||
self.__input_queue,
|
self._input_queue,
|
||||||
self.__output_queue,
|
self._output_queue,
|
||||||
self.__config_paths
|
self.__config_paths
|
||||||
)
|
)
|
||||||
self.__auto_lib_thread.finishedSignal.connect(self.onStopButtonClicked)
|
self.__auto_lib_thread.AutoLibWorkerIsFinished.connect(self.onStopButtonClicked)
|
||||||
self.__auto_lib_thread.finishedWithErrorSignal.connect(self.onStopButtonClicked)
|
self.__auto_lib_thread.AutoLibWorkerFinishedWithError.connect(self.onStopButtonClicked)
|
||||||
self.__auto_lib_thread.start()
|
self.__auto_lib_thread.start()
|
||||||
|
|
||||||
@Slot()
|
@Slot()
|
||||||
@@ -397,11 +380,11 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
):
|
):
|
||||||
|
|
||||||
if self.__auto_lib_thread:
|
if self.__auto_lib_thread:
|
||||||
self.showTrace("正在停止操作......")
|
self._showTrace("正在停止操作......")
|
||||||
self.__auto_lib_thread.wait(2000)
|
self.__auto_lib_thread.wait(2000)
|
||||||
self.showTrace("操作已停止")
|
self._showTrace("操作已停止")
|
||||||
self.__auto_lib_thread.finishedSignal.disconnect(self.onStopButtonClicked)
|
self.__auto_lib_thread.AutoLibWorkerIsFinished.disconnect(self.onStopButtonClicked)
|
||||||
self.__auto_lib_thread.finishedWithErrorSignal.disconnect(self.onStopButtonClicked)
|
self.__auto_lib_thread.AutoLibWorkerFinishedWithError.disconnect(self.onStopButtonClicked)
|
||||||
self.__auto_lib_thread.deleteLater()
|
self.__auto_lib_thread.deleteLater()
|
||||||
self.__auto_lib_thread = None
|
self.__auto_lib_thread = None
|
||||||
self.setControlButtons(None, False, True)
|
self.setControlButtons(None, False, True)
|
||||||
@@ -414,6 +397,6 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
msg = self.MessageEdit.text().strip()
|
msg = self.MessageEdit.text().strip()
|
||||||
if not msg:
|
if not msg:
|
||||||
return
|
return
|
||||||
self.showMsg(msg)
|
self._showMsg(msg)
|
||||||
self.__input_queue.put(msg) # put message to input queue
|
self._input_queue.put(msg) # put message to input queue
|
||||||
self.MessageEdit.clear()
|
self.MessageEdit.clear()
|
||||||
+14
-14
@@ -20,10 +20,10 @@ from operators.AutoLib import AutoLib
|
|||||||
from utils.ConfigReader import ConfigReader
|
from utils.ConfigReader import ConfigReader
|
||||||
|
|
||||||
|
|
||||||
class AutoLibWorker(QThread, MsgBase):
|
class AutoLibWorker(MsgBase, QThread):
|
||||||
|
|
||||||
finishedSignal = Signal()
|
AutoLibWorkerIsFinished = Signal()
|
||||||
finishedWithErrorSignal = Signal()
|
AutoLibWorkerFinishedWithError = Signal()
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -32,8 +32,8 @@ class AutoLibWorker(QThread, MsgBase):
|
|||||||
config_paths: dict
|
config_paths: dict
|
||||||
):
|
):
|
||||||
|
|
||||||
super().__init__(input_queue=input_queue, output_queue=output_queue)
|
MsgBase.__init__(self, input_queue, output_queue)
|
||||||
|
QThread.__init__(self)
|
||||||
self.__config_paths = config_paths
|
self.__config_paths = config_paths
|
||||||
|
|
||||||
|
|
||||||
@@ -116,17 +116,17 @@ class AutoLibWorker(QThread, MsgBase):
|
|||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._showTrace(f"AutoLibrary 运行时发生异常 : {e}")
|
self._showTrace(f"AutoLibrary 运行时发生异常 : {e}")
|
||||||
self.finishedWithErrorSignal.emit()
|
self.AutoLibWorkerFinishedWithError.emit()
|
||||||
return
|
return
|
||||||
if auto_lib:
|
if auto_lib:
|
||||||
auto_lib.close()
|
auto_lib.close()
|
||||||
self._showTrace("AutoLibrary 运行结束")
|
self._showTrace("AutoLibrary 运行结束")
|
||||||
self.finishedSignal.emit()
|
self.AutoLibWorkerIsFinished.emit()
|
||||||
|
|
||||||
|
|
||||||
class TimerTaskWorker(AutoLibWorker):
|
class TimerTaskWorker(AutoLibWorker):
|
||||||
|
|
||||||
finishedSignal_TimerWorker = Signal(bool, dict)
|
TimerTaskWorkerIsFinished = Signal(bool, dict)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -139,8 +139,8 @@ class TimerTaskWorker(AutoLibWorker):
|
|||||||
super().__init__(input_queue, output_queue, config_paths)
|
super().__init__(input_queue, output_queue, config_paths)
|
||||||
|
|
||||||
self.__timer_task = timer_task
|
self.__timer_task = timer_task
|
||||||
self.finishedSignal.connect(self.onTimerTaskIsFinished)
|
self.AutoLibWorkerIsFinished.connect(self.onTimerTaskIsFinished)
|
||||||
self.finishedWithErrorSignal.connect(self.onTimerTaskIsError)
|
self.AutoLibWorkerFinishedWithError.connect(self.onTimerTaskIsError)
|
||||||
|
|
||||||
def run(
|
def run(
|
||||||
self
|
self
|
||||||
@@ -149,18 +149,18 @@ class TimerTaskWorker(AutoLibWorker):
|
|||||||
self._showTrace(f"定时任务 {self.__timer_task['name']} 开始运行")
|
self._showTrace(f"定时任务 {self.__timer_task['name']} 开始运行")
|
||||||
super().run()
|
super().run()
|
||||||
|
|
||||||
@Slot(dict)
|
@Slot()
|
||||||
def onTimerTaskIsError(
|
def onTimerTaskIsError(
|
||||||
self
|
self
|
||||||
):
|
):
|
||||||
|
|
||||||
self._showTrace(f"定时任务 {self.__timer_task['name']} 运行时发生异常")
|
self._showTrace(f"定时任务 {self.__timer_task['name']} 运行时发生异常")
|
||||||
self.finishedSignal_TimerWorker.emit(True, self.__timer_task)
|
self.TimerTaskWorkerIsFinished.emit(True, self.__timer_task)
|
||||||
|
|
||||||
@Slot(dict)
|
@Slot()
|
||||||
def onTimerTaskIsFinished(
|
def onTimerTaskIsFinished(
|
||||||
self
|
self
|
||||||
):
|
):
|
||||||
|
|
||||||
self._showTrace(f"定时任务 {self.__timer_task['name']} 运行结束")
|
self._showTrace(f"定时任务 {self.__timer_task['name']} 运行结束")
|
||||||
self.finishedSignal_TimerWorker.emit(False, self.__timer_task)
|
self.TimerTaskWorkerIsFinished.emit(False, self.__timer_task)
|
||||||
|
|||||||
+13
-12
@@ -22,7 +22,7 @@ class ALSeatFrame(QFrame):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
seat_number,
|
seat_number,
|
||||||
parent=None
|
parent = None
|
||||||
):
|
):
|
||||||
|
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
@@ -40,18 +40,19 @@ class ALSeatFrame(QFrame):
|
|||||||
self.setLineWidth(2)
|
self.setLineWidth(2)
|
||||||
self.setStyleSheet("""
|
self.setStyleSheet("""
|
||||||
QFrame {
|
QFrame {
|
||||||
background-color: #4196EB;
|
background-color: #2294FF;
|
||||||
border: 2px solid #4196EB;
|
border: 2px solid #2294FF;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
QLabel {
|
QLabel {
|
||||||
color: #F0F0F0;
|
color: #FFFFFF;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
self.label = QLabel(self.__seat_number, self)
|
self.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||||
self.label.setAlignment(Qt.AlignCenter)
|
self.Label = QLabel(self.__seat_number, self)
|
||||||
self.label.setGeometry(0, 0, 60, 40)
|
self.Label.setAlignment(Qt.AlignCenter)
|
||||||
|
self.Label.setGeometry(0, 0, 60, 40)
|
||||||
|
|
||||||
def mousePressEvent(
|
def mousePressEvent(
|
||||||
self,
|
self,
|
||||||
@@ -77,24 +78,24 @@ class ALSeatFrame(QFrame):
|
|||||||
self.setStyleSheet("""
|
self.setStyleSheet("""
|
||||||
QFrame {
|
QFrame {
|
||||||
background-color: #4CAF50;
|
background-color: #4CAF50;
|
||||||
border: 2px solid #388E3C;
|
border: 2px solid #4CAF50;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
QLabel {
|
QLabel {
|
||||||
color: #F0F0F0;
|
color: #FFFFFF;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
else:
|
else:
|
||||||
self.setStyleSheet("""
|
self.setStyleSheet("""
|
||||||
QFrame {
|
QFrame {
|
||||||
background-color: #4196EB;
|
background-color: #2294FF;
|
||||||
border: 2px solid #4196EB;
|
border: 2px solid #2294FF;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
QLabel {
|
QLabel {
|
||||||
color: #F0F0F0;
|
color: #FFFFFF;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Copyright (c) 2025 - 2026 KenanZhu.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This software is provided "as is", without any warranty of any kind.
|
||||||
|
You may use, modify, and distribute this file under the terms of the MIT License.
|
||||||
|
See the LICENSE file for details.
|
||||||
|
"""
|
||||||
|
from PySide6.QtCore import (
|
||||||
|
Qt, Slot, Signal
|
||||||
|
)
|
||||||
|
from PySide6.QtWidgets import (
|
||||||
|
QDialog, QLabel, QHBoxLayout, QVBoxLayout,
|
||||||
|
QPushButton,
|
||||||
|
)
|
||||||
|
from PySide6.QtGui import (
|
||||||
|
QCloseEvent
|
||||||
|
)
|
||||||
|
from gui.ALSeatMapView import ALSeatMapView
|
||||||
|
|
||||||
|
|
||||||
|
class ALSeatMapSelectDialog(QDialog):
|
||||||
|
|
||||||
|
seatMapSelectDialogClosed = Signal(list)
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
parent: QDialog = None,
|
||||||
|
floor: str = "",
|
||||||
|
room: str = "",
|
||||||
|
seats_data: str = ""
|
||||||
|
):
|
||||||
|
|
||||||
|
super().__init__(parent)
|
||||||
|
self.__floor = floor
|
||||||
|
self.__room = room
|
||||||
|
self.__seats_data = seats_data
|
||||||
|
self.__confirmed = False
|
||||||
|
|
||||||
|
self.setupUi()
|
||||||
|
self.connectSignals()
|
||||||
|
|
||||||
|
|
||||||
|
def setupUi(
|
||||||
|
self
|
||||||
|
):
|
||||||
|
|
||||||
|
self.setModal(True)
|
||||||
|
self.setMinimumSize(800, 600)
|
||||||
|
self.resize(800, 600)
|
||||||
|
self.setWindowTitle(f"选择楼层座位 - AutoLibrary")
|
||||||
|
|
||||||
|
self.SeatMapWidgetMainLayout = QVBoxLayout(self)
|
||||||
|
self.SeatMapWidgetMainLayout.setContentsMargins(5, 5, 5, 5)
|
||||||
|
self.SeatMapWidgetMainLayout.setSpacing(5)
|
||||||
|
self.TitleLabel = QLabel(f"楼层座位分布图: {self.__floor}-{self.__room}")
|
||||||
|
self.TitleLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
|
self.TitleLabel.setStyleSheet("font-size: 16px; font-weight: bold; margin: 10px;")
|
||||||
|
self.SeatMapWidgetMainLayout.addWidget(self.TitleLabel)
|
||||||
|
|
||||||
|
self.SeatMapGraphicsView = ALSeatMapView(None, self.__seats_data)
|
||||||
|
self.SeatMapWidgetMainLayout.addWidget(self.SeatMapGraphicsView)
|
||||||
|
|
||||||
|
self.TipsLabel = QLabel(
|
||||||
|
" 点击座位进行选择/取消选择, 最多选择1个座位 \n"
|
||||||
|
" [操作方法: Ctrl+鼠标滚轮缩放 | 滚轮/拖拽/方向键 移动]"
|
||||||
|
)
|
||||||
|
self.TipsLabel.setAlignment(Qt.AlignmentFlag.AlignLeft)
|
||||||
|
self.TipsLabel.setStyleSheet("color: #666; margin: 5px;")
|
||||||
|
self.SeatMapWidgetMainLayout.addWidget(self.TipsLabel)
|
||||||
|
|
||||||
|
self.ConfirmButton = QPushButton("确认")
|
||||||
|
self.ConfirmButton.setFixedSize(80, 25)
|
||||||
|
self.ConfirmButton.setAutoDefault(True)
|
||||||
|
self.ConfirmButton.setDefault(True)
|
||||||
|
self.CancelButton = QPushButton("取消")
|
||||||
|
self.CancelButton.setFixedSize(80, 25)
|
||||||
|
self.SeatMapWidgetControlLayout = QHBoxLayout()
|
||||||
|
self.SeatMapWidgetControlLayout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.SeatMapWidgetControlLayout.setSpacing(5)
|
||||||
|
self.SeatMapWidgetControlLayout.setAlignment(Qt.AlignmentFlag.AlignRight)
|
||||||
|
self.SeatMapWidgetControlLayout.addWidget(self.CancelButton)
|
||||||
|
self.SeatMapWidgetControlLayout.addWidget(self.ConfirmButton)
|
||||||
|
self.SeatMapWidgetMainLayout.addLayout(self.SeatMapWidgetControlLayout)
|
||||||
|
|
||||||
|
|
||||||
|
def connectSignals(
|
||||||
|
self
|
||||||
|
):
|
||||||
|
|
||||||
|
self.ConfirmButton.clicked.connect(self.onConfirmButtonClicked)
|
||||||
|
self.CancelButton.clicked.connect(self.onCancelButtonClicked)
|
||||||
|
|
||||||
|
|
||||||
|
def showEvent(
|
||||||
|
self,
|
||||||
|
event
|
||||||
|
):
|
||||||
|
|
||||||
|
result = super().showEvent(event)
|
||||||
|
|
||||||
|
screen_rect = self.screen().geometry()
|
||||||
|
target_pos = self.parent().geometry().center()
|
||||||
|
target_pos.setX(target_pos.x() - self.width()//2)
|
||||||
|
target_pos.setY(target_pos.y() - self.height()//2)
|
||||||
|
if target_pos.x() < 0:
|
||||||
|
target_pos.setX(0)
|
||||||
|
if target_pos.x() + self.width() > screen_rect.width():
|
||||||
|
target_pos.setX(screen_rect.width() - self.width())
|
||||||
|
if target_pos.y() < 0:
|
||||||
|
target_pos.setY(0)
|
||||||
|
if target_pos.y() + self.height() > screen_rect.height():
|
||||||
|
target_pos.setY(screen_rect.height() - self.height())
|
||||||
|
self.move(target_pos)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def closeEvent(
|
||||||
|
self,
|
||||||
|
event: QCloseEvent
|
||||||
|
):
|
||||||
|
|
||||||
|
if not self.__confirmed:
|
||||||
|
self.clearSelections()
|
||||||
|
self.reject()
|
||||||
|
else:
|
||||||
|
self.accept()
|
||||||
|
self.seatMapSelectDialogClosed.emit(self.getSelectedSeats())
|
||||||
|
super().closeEvent(event)
|
||||||
|
|
||||||
|
|
||||||
|
def selectSeat(
|
||||||
|
self,
|
||||||
|
seat_number: str
|
||||||
|
):
|
||||||
|
|
||||||
|
self.SeatMapGraphicsView.selectSeat(seat_number)
|
||||||
|
|
||||||
|
|
||||||
|
def selectSeats(
|
||||||
|
self,
|
||||||
|
seat_numbers: list[str]
|
||||||
|
) -> bool:
|
||||||
|
|
||||||
|
return self.SeatMapGraphicsView.selectSeats(seat_numbers)
|
||||||
|
|
||||||
|
|
||||||
|
def getSelectedSeats(
|
||||||
|
self
|
||||||
|
) -> list[str]:
|
||||||
|
|
||||||
|
return self.SeatMapGraphicsView.getSelectedSeats()
|
||||||
|
|
||||||
|
|
||||||
|
def clearSelections(
|
||||||
|
self
|
||||||
|
):
|
||||||
|
|
||||||
|
self.SeatMapGraphicsView.clearSelections()
|
||||||
|
|
||||||
|
@Slot()
|
||||||
|
def onConfirmButtonClicked(
|
||||||
|
self
|
||||||
|
):
|
||||||
|
|
||||||
|
self.__confirmed = True
|
||||||
|
self.accept()
|
||||||
|
|
||||||
|
@Slot()
|
||||||
|
def onCancelButtonClicked(
|
||||||
|
self
|
||||||
|
):
|
||||||
|
|
||||||
|
self.__confirmed = False
|
||||||
|
self.reject()
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
seats_maps = {
|
ALSeatMapTable = {
|
||||||
"2": {
|
"2": {
|
||||||
"1": """
|
"1": """
|
||||||
,,,,,,,,,,,039A,039B,,040A,040B,,041A,041B,,042A,042B,,043A,043B,,044A,044B,,,,,,,,,
|
,,,,,,,,,,,039A,039B,,040A,040B,,041A,041B,,042A,042B,,043A,043B,,044A,044B,,,,,,,,,
|
||||||
|
|||||||
@@ -8,41 +8,31 @@ You may use, modify, and distribute this file under the terms of the MIT License
|
|||||||
See the LICENSE file for details.
|
See the LICENSE file for details.
|
||||||
"""
|
"""
|
||||||
from PySide6.QtCore import (
|
from PySide6.QtCore import (
|
||||||
Qt, Slot, Signal, QEvent
|
Qt, Slot, QEvent
|
||||||
)
|
)
|
||||||
from PySide6.QtWidgets import (
|
from PySide6.QtWidgets import (
|
||||||
QFrame, QWidget, QLabel, QHBoxLayout, QVBoxLayout,
|
QFrame, QWidget,
|
||||||
QGridLayout, QGraphicsView, QGraphicsScene, QGraphicsItem,
|
QGridLayout, QGraphicsView, QGraphicsScene, QGraphicsItem
|
||||||
QPushButton,
|
|
||||||
)
|
)
|
||||||
from PySide6.QtGui import (
|
from PySide6.QtGui import (
|
||||||
QPainter, QWheelEvent, QCloseEvent
|
QPainter, QWheelEvent
|
||||||
)
|
)
|
||||||
from gui.ALSeatFrame import ALSeatFrame
|
from gui.ALSeatFrame import ALSeatFrame
|
||||||
|
|
||||||
|
|
||||||
class ALSeatMapWidget(QWidget):
|
class ALSeatMapView(QGraphicsView):
|
||||||
|
|
||||||
seatMapWidgetClosed = Signal(list)
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
parent: QWidget = None,
|
parent: QWidget = None,
|
||||||
floor: str = "",
|
|
||||||
room: str = "",
|
|
||||||
seats_data: dict = {},
|
seats_data: dict = {},
|
||||||
):
|
):
|
||||||
|
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.__floor = floor
|
|
||||||
self.__room = room
|
|
||||||
self.__seats_data = seats_data
|
self.__seats_data = seats_data
|
||||||
self.__selected_seats = []
|
self.__selected_seats = []
|
||||||
self.__seat_frames = {}
|
self.__seat_frames = {}
|
||||||
self.__confirmed = False
|
|
||||||
|
|
||||||
self.setupUi()
|
self.setupUi()
|
||||||
self.connectSignals()
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def formatSeatNumber(
|
def formatSeatNumber(
|
||||||
@@ -56,108 +46,13 @@ class ALSeatMapWidget(QWidget):
|
|||||||
return seat_number.zfill(3)
|
return seat_number.zfill(3)
|
||||||
|
|
||||||
|
|
||||||
def setupUi(
|
|
||||||
self
|
|
||||||
):
|
|
||||||
|
|
||||||
self.setWindowFlags(Qt.WindowType.Window)
|
|
||||||
self.setWindowModality(Qt.WindowModality.ApplicationModal)
|
|
||||||
self.setMinimumSize(800, 600)
|
|
||||||
self.resize(800, 600)
|
|
||||||
self.setWindowTitle(f"选择楼层座位 - AutoLibrary")
|
|
||||||
|
|
||||||
self.SeatMapWidgetMainLayout = QVBoxLayout(self)
|
|
||||||
self.TitleLabel = QLabel(f"楼层座位分布图: {self.__floor}-{self.__room}")
|
|
||||||
self.TitleLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
||||||
self.TitleLabel.setStyleSheet("font-size: 16px; font-weight: bold; margin: 10px;")
|
|
||||||
self.SeatMapWidgetMainLayout.addWidget(self.TitleLabel)
|
|
||||||
|
|
||||||
self.SeatMapGraphicsView = QGraphicsView(self)
|
|
||||||
self.SeatMapGraphicsScene = QGraphicsScene(self)
|
|
||||||
self.SeatMapGraphicsView.setScene(self.SeatMapGraphicsScene)
|
|
||||||
self.SeatMapGraphicsView.setRenderHint(QPainter.RenderHint.LosslessImageRendering)
|
|
||||||
self.SeatMapGraphicsView.setDragMode(QGraphicsView.DragMode.ScrollHandDrag)
|
|
||||||
self.SeatMapGraphicsView.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
|
||||||
self.SeatMapGraphicsView.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
|
||||||
self.SeatMapGraphicsView.viewport().installEventFilter(self)
|
|
||||||
|
|
||||||
self.SeatsContainerWidget = QWidget()
|
|
||||||
self.SeatsContainerLayout = QGridLayout(self.SeatsContainerWidget)
|
|
||||||
self.createSeatMap()
|
|
||||||
|
|
||||||
self.ContainerProxy = self.SeatMapGraphicsScene.addWidget(self.SeatsContainerWidget)
|
|
||||||
self.ContainerProxy.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable, False)
|
|
||||||
self.SeatMapWidgetMainLayout.addWidget(self.SeatMapGraphicsView)
|
|
||||||
|
|
||||||
self.TipsLabel = QLabel(
|
|
||||||
" 点击座位进行选择/取消选择, 最多选择1个座位 \n"
|
|
||||||
" [操作方法: Ctrl+鼠标滚轮缩放 | 滚轮/拖拽/方向键 移动]"
|
|
||||||
)
|
|
||||||
self.TipsLabel.setAlignment(Qt.AlignmentFlag.AlignLeft)
|
|
||||||
self.TipsLabel.setStyleSheet("color: #666; margin: 5px;")
|
|
||||||
self.SeatMapWidgetMainLayout.addWidget(self.TipsLabel)
|
|
||||||
|
|
||||||
self.ConfirmButton = QPushButton("确认")
|
|
||||||
self.ConfirmButton.setFixedSize(80, 25)
|
|
||||||
self.CancelButton = QPushButton("取消")
|
|
||||||
self.CancelButton.setFixedSize(80, 25)
|
|
||||||
self.SeatMapWidgetControlLayout = QHBoxLayout()
|
|
||||||
self.SeatMapWidgetControlLayout.setAlignment(Qt.AlignmentFlag.AlignRight)
|
|
||||||
self.SeatMapWidgetControlLayout.addWidget(self.CancelButton)
|
|
||||||
self.SeatMapWidgetControlLayout.addWidget(self.ConfirmButton)
|
|
||||||
self.SeatMapWidgetMainLayout.addLayout(self.SeatMapWidgetControlLayout)
|
|
||||||
|
|
||||||
|
|
||||||
def connectSignals(
|
|
||||||
self
|
|
||||||
):
|
|
||||||
|
|
||||||
self.ConfirmButton.clicked.connect(self.onConfirmButtonClicked)
|
|
||||||
self.CancelButton.clicked.connect(self.onCancelButtonClicked)
|
|
||||||
|
|
||||||
|
|
||||||
def showEvent(
|
|
||||||
self,
|
|
||||||
event
|
|
||||||
):
|
|
||||||
|
|
||||||
result = super().showEvent(event)
|
|
||||||
|
|
||||||
screen_rect = self.screen().geometry()
|
|
||||||
target_pos = self.parent().geometry().center()
|
|
||||||
target_pos.setX(target_pos.x() - self.width()//2)
|
|
||||||
target_pos.setY(target_pos.y() - self.height()//2)
|
|
||||||
if target_pos.x() < 0:
|
|
||||||
target_pos.setX(0)
|
|
||||||
if target_pos.x() + self.width() > screen_rect.width():
|
|
||||||
target_pos.setX(screen_rect.width() - self.width())
|
|
||||||
if target_pos.y() < 0:
|
|
||||||
target_pos.setY(0)
|
|
||||||
if target_pos.y() + self.height() > screen_rect.height():
|
|
||||||
target_pos.setY(screen_rect.height() - self.height())
|
|
||||||
self.move(target_pos)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def closeEvent(
|
|
||||||
self,
|
|
||||||
event: QCloseEvent
|
|
||||||
):
|
|
||||||
|
|
||||||
if not self.__confirmed:
|
|
||||||
self.clearSelections()
|
|
||||||
self.seatMapWidgetClosed.emit(self.__selected_seats)
|
|
||||||
super().closeEvent(event)
|
|
||||||
|
|
||||||
|
|
||||||
def eventFilter(
|
def eventFilter(
|
||||||
self,
|
self,
|
||||||
watched,
|
watched,
|
||||||
event
|
event
|
||||||
):
|
):
|
||||||
|
|
||||||
if (watched is self.SeatMapGraphicsView.viewport() and
|
if (watched is self.viewport() and
|
||||||
event.type() == QEvent.Type.Wheel and
|
event.type() == QEvent.Type.Wheel and
|
||||||
event.modifiers() == Qt.KeyboardModifier.ControlModifier
|
event.modifiers() == Qt.KeyboardModifier.ControlModifier
|
||||||
):
|
):
|
||||||
@@ -172,12 +67,40 @@ class ALSeatMapWidget(QWidget):
|
|||||||
):
|
):
|
||||||
|
|
||||||
delta = event.angleDelta().y()
|
delta = event.angleDelta().y()
|
||||||
|
min_scale = 0.1
|
||||||
|
max_scale = 4.0
|
||||||
|
current_scale = self.transform().m11()
|
||||||
zoom_factor = 1.2 if delta > 0 else 1/1.2
|
zoom_factor = 1.2 if delta > 0 else 1/1.2
|
||||||
self.SeatMapGraphicsView.setTransformationAnchor(QGraphicsView.ViewportAnchor.AnchorUnderMouse)
|
target_scale = current_scale*zoom_factor
|
||||||
self.SeatMapGraphicsView.scale(zoom_factor, zoom_factor)
|
if target_scale < min_scale and delta < 0:
|
||||||
|
return
|
||||||
|
if target_scale > max_scale and delta > 0:
|
||||||
|
return
|
||||||
|
self.setTransformationAnchor(QGraphicsView.ViewportAnchor.AnchorUnderMouse)
|
||||||
|
self.scale(zoom_factor, zoom_factor)
|
||||||
|
|
||||||
|
|
||||||
def createSeatMap(
|
def setupUi(
|
||||||
|
self
|
||||||
|
):
|
||||||
|
|
||||||
|
self.SeatMapGraphicsScene = QGraphicsScene(self)
|
||||||
|
self.setScene(self.SeatMapGraphicsScene)
|
||||||
|
self.setRenderHint(QPainter.RenderHint.LosslessImageRendering)
|
||||||
|
self.setDragMode(QGraphicsView.DragMode.ScrollHandDrag)
|
||||||
|
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
||||||
|
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
||||||
|
self.viewport().installEventFilter(self)
|
||||||
|
|
||||||
|
self.SeatsContainerWidget = QWidget()
|
||||||
|
self.SeatsContainerLayout = QGridLayout(self.SeatsContainerWidget)
|
||||||
|
self.setupSeatMap()
|
||||||
|
|
||||||
|
self.ContainerProxy = self.SeatMapGraphicsScene.addWidget(self.SeatsContainerWidget)
|
||||||
|
self.ContainerProxy.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable, False)
|
||||||
|
|
||||||
|
|
||||||
|
def setupSeatMap(
|
||||||
self
|
self
|
||||||
):
|
):
|
||||||
|
|
||||||
@@ -262,19 +185,3 @@ class ALSeatMapWidget(QWidget):
|
|||||||
self.__selected_seats.append(seat_number)
|
self.__selected_seats.append(seat_number)
|
||||||
else:
|
else:
|
||||||
self.__seat_frames[seat_number].toggleSelection()
|
self.__seat_frames[seat_number].toggleSelection()
|
||||||
|
|
||||||
@Slot()
|
|
||||||
def onConfirmButtonClicked(
|
|
||||||
self
|
|
||||||
):
|
|
||||||
|
|
||||||
self.__confirmed = True
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
@Slot()
|
|
||||||
def onCancelButtonClicked(
|
|
||||||
self
|
|
||||||
):
|
|
||||||
|
|
||||||
self.__confirmed = False
|
|
||||||
self.close()
|
|
||||||
@@ -20,10 +20,10 @@ from PySide6.QtWidgets import (
|
|||||||
QHBoxLayout, QGridLayout, QDateTimeEdit
|
QHBoxLayout, QGridLayout, QDateTimeEdit
|
||||||
)
|
)
|
||||||
|
|
||||||
from gui.Ui_ALAddTimerTaskDialog import Ui_ALAddTimerTaskDialog
|
from gui.resources.ui.Ui_ALTimerTaskAddDialog import Ui_ALTimerTaskAddDialog
|
||||||
|
|
||||||
|
|
||||||
class TimerTaskStatus(Enum):
|
class ALTimerTaskStatus(Enum):
|
||||||
|
|
||||||
PENDING = "等待中"
|
PENDING = "等待中"
|
||||||
READY = "已就绪"
|
READY = "已就绪"
|
||||||
@@ -33,7 +33,7 @@ class TimerTaskStatus(Enum):
|
|||||||
OUTDATED = "已过期"
|
OUTDATED = "已过期"
|
||||||
|
|
||||||
|
|
||||||
class ALAddTimerTaskWidget(QDialog, Ui_ALAddTimerTaskDialog):
|
class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -128,7 +128,7 @@ class ALAddTimerTaskWidget(QDialog, Ui_ALAddTimerTaskDialog):
|
|||||||
"execute_time": execute_time,
|
"execute_time": execute_time,
|
||||||
"silent": silent,
|
"silent": silent,
|
||||||
"add_time": added_time,
|
"add_time": added_time,
|
||||||
"status": TimerTaskStatus.PENDING,
|
"status": ALTimerTaskStatus.PENDING,
|
||||||
"executed": False
|
"executed": False
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,21 +24,14 @@ from PySide6.QtGui import (
|
|||||||
QCloseEvent
|
QCloseEvent
|
||||||
)
|
)
|
||||||
|
|
||||||
from gui.Ui_ALTimerTaskWidget import Ui_ALTimerTaskWidget
|
from gui.resources.ui.Ui_ALTimerTaskManageWidget import Ui_ALTimerTaskManageWidget
|
||||||
from gui.ALAddTimerTaskDialog import ALAddTimerTaskWidget, TimerTaskStatus
|
from gui.ALTimerTaskAddDialog import ALTimerTaskAddDialog, ALTimerTaskStatus
|
||||||
|
|
||||||
from utils.ConfigReader import ConfigReader
|
from utils.ConfigReader import ConfigReader
|
||||||
from utils.ConfigWriter import ConfigWriter
|
from utils.ConfigWriter import ConfigWriter
|
||||||
|
|
||||||
|
|
||||||
class SortPolicy(Enum):
|
class ALTimerTaskItemWidget(QWidget):
|
||||||
|
|
||||||
BY_NAME = "按名称"
|
|
||||||
BY_ADD_TIME = "按添加时间"
|
|
||||||
BY_EXECUTE_TIME = "按执行时间"
|
|
||||||
|
|
||||||
|
|
||||||
class TimerTaskItemWidget(QWidget):
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -71,7 +64,7 @@ class TimerTaskItemWidget(QWidget):
|
|||||||
|
|
||||||
ExecuteTimeStr = self.__timer_task["execute_time"].strftime("%Y-%m-%d %H:%M:%S")
|
ExecuteTimeStr = self.__timer_task["execute_time"].strftime("%Y-%m-%d %H:%M:%S")
|
||||||
ExecuteTimeLabel = QLabel(f"执行时间: {ExecuteTimeStr}")
|
ExecuteTimeLabel = QLabel(f"执行时间: {ExecuteTimeStr}")
|
||||||
ExecuteTimeLabel.setStyleSheet("color: gray;")
|
ExecuteTimeLabel.setStyleSheet("color: #969696;")
|
||||||
ExecuteTimeLabel.setFixedHeight(20)
|
ExecuteTimeLabel.setFixedHeight(20)
|
||||||
self.TaskInfoLayout.addWidget(ExecuteTimeLabel)
|
self.TaskInfoLayout.addWidget(ExecuteTimeLabel)
|
||||||
|
|
||||||
@@ -79,29 +72,29 @@ class TimerTaskItemWidget(QWidget):
|
|||||||
self.ItemWidgetLayout.addStretch()
|
self.ItemWidgetLayout.addStretch()
|
||||||
|
|
||||||
match self.__timer_task["status"]:
|
match self.__timer_task["status"]:
|
||||||
case TimerTaskStatus.PENDING:
|
case ALTimerTaskStatus.PENDING:
|
||||||
TaskStatusText = "等待中"
|
TaskStatusText = "等待中"
|
||||||
TaskStatusColor = "#FF9800"
|
TaskStatusColor = "#FF9800"
|
||||||
case TimerTaskStatus.READY:
|
case ALTimerTaskStatus.READY:
|
||||||
TaskStatusText = "已就绪"
|
TaskStatusText = "已就绪"
|
||||||
TaskStatusColor = "#316BFF"
|
TaskStatusColor = "#316BFF"
|
||||||
case TimerTaskStatus.RUNNING:
|
case ALTimerTaskStatus.RUNNING:
|
||||||
TaskStatusText = "执行中"
|
TaskStatusText = "执行中"
|
||||||
TaskStatusColor = "#2294FF"
|
TaskStatusColor = "#2294FF"
|
||||||
case TimerTaskStatus.EXECUTED:
|
case ALTimerTaskStatus.EXECUTED:
|
||||||
TaskStatusText = "已执行"
|
TaskStatusText = "已执行"
|
||||||
TaskStatusColor = "#4CAF50"
|
TaskStatusColor = "#4CAF50"
|
||||||
case TimerTaskStatus.ERROR:
|
case ALTimerTaskStatus.ERROR:
|
||||||
TaskStatusText = "执行失败"
|
TaskStatusText = "执行失败"
|
||||||
TaskStatusColor = "#FF5722"
|
TaskStatusColor = "#DC0000"
|
||||||
case TimerTaskStatus.OUTDATED:
|
case ALTimerTaskStatus.OUTDATED:
|
||||||
TaskStatusText = "已过期"
|
TaskStatusText = "已过期"
|
||||||
TaskStatusColor = "#FF5722"
|
TaskStatusColor = "#DC0000"
|
||||||
TaskStatusLabel = QLabel(TaskStatusText)
|
TaskStatusLabel = QLabel(TaskStatusText)
|
||||||
TaskStatusLabel.setStyleSheet(f"""
|
TaskStatusLabel.setStyleSheet(f"""
|
||||||
QLabel {{
|
QLabel {{
|
||||||
background-color: {TaskStatusColor};
|
background-color: {TaskStatusColor};
|
||||||
color: white;
|
color: #FFFFFF;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}}
|
}}
|
||||||
@@ -116,7 +109,7 @@ class TimerTaskItemWidget(QWidget):
|
|||||||
TaskModeLabel.setStyleSheet(f"""
|
TaskModeLabel.setStyleSheet(f"""
|
||||||
QLabel {{
|
QLabel {{
|
||||||
background-color: {TaskModeColor};
|
background-color: {TaskModeColor};
|
||||||
color: white;
|
color: #FFFFFF;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}}
|
}}
|
||||||
@@ -128,17 +121,23 @@ class TimerTaskItemWidget(QWidget):
|
|||||||
self.DeleteButton = QPushButton("删除")
|
self.DeleteButton = QPushButton("删除")
|
||||||
self.DeleteButton.setFixedSize(80, 25)
|
self.DeleteButton.setFixedSize(80, 25)
|
||||||
self.ItemWidgetLayout.addWidget(self.DeleteButton)
|
self.ItemWidgetLayout.addWidget(self.DeleteButton)
|
||||||
if self.__timer_task["status"] == TimerTaskStatus.READY\
|
if self.__timer_task["status"] == ALTimerTaskStatus.READY\
|
||||||
or self.__timer_task["status"] == TimerTaskStatus.RUNNING:
|
or self.__timer_task["status"] == ALTimerTaskStatus.RUNNING:
|
||||||
self.DeleteButton.setEnabled(False)
|
self.DeleteButton.setEnabled(False)
|
||||||
self.setFixedHeight(55)
|
self.setFixedHeight(55)
|
||||||
|
|
||||||
|
|
||||||
class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
|
||||||
|
|
||||||
|
class SortPolicy(Enum):
|
||||||
|
|
||||||
|
BY_NAME = "按名称"
|
||||||
|
BY_ADD_TIME = "按添加时间"
|
||||||
|
BY_EXECUTE_TIME = "按执行时间"
|
||||||
|
|
||||||
timerTasksChanged = Signal()
|
|
||||||
timerTaskIsReady = Signal(dict)
|
timerTaskIsReady = Signal(dict)
|
||||||
timerTaskWidgetClosed = Signal()
|
timerTasksChanged = Signal()
|
||||||
|
timerTaskManageWidgetClosed = Signal()
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -147,10 +146,9 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
):
|
):
|
||||||
|
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
self.__timer_tasks = []
|
self.__timer_tasks = []
|
||||||
self.__check_timer = None
|
self.__check_timer = None
|
||||||
self.__sort_policy = SortPolicy.BY_EXECUTE_TIME
|
self.__sort_policy = self.SortPolicy.BY_EXECUTE_TIME
|
||||||
self.__sort_order = Qt.SortOrder.AscendingOrder
|
self.__sort_order = Qt.SortOrder.AscendingOrder
|
||||||
self.__timer_tasks_config_path = timer_tasks_config_path
|
self.__timer_tasks_config_path = timer_tasks_config_path
|
||||||
|
|
||||||
@@ -158,7 +156,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
self.connectSignals()
|
self.connectSignals()
|
||||||
self.setupTimer()
|
self.setupTimer()
|
||||||
if not self.initializeTimerTasks():
|
if not self.initializeTimerTasks():
|
||||||
return
|
raise Exception("定时任务配置文件初始化失败 !")
|
||||||
|
|
||||||
|
|
||||||
def connectSignals(
|
def connectSignals(
|
||||||
@@ -192,11 +190,6 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
return True
|
return True
|
||||||
timer_tasks = []
|
timer_tasks = []
|
||||||
if self.saveTimerTasks(self.__timer_tasks_config_path, copy.deepcopy(timer_tasks)):
|
if self.saveTimerTasks(self.__timer_tasks_config_path, copy.deepcopy(timer_tasks)):
|
||||||
QMessageBox.information(
|
|
||||||
self,
|
|
||||||
"信息 - AutoLibrary",
|
|
||||||
f"定时任务配置文件初始化完成: \n{self.__timer_tasks_config_path}"
|
|
||||||
)
|
|
||||||
self.__timer_tasks = timer_tasks
|
self.__timer_tasks = timer_tasks
|
||||||
self.updateTimerTaskList()
|
self.updateTimerTaskList()
|
||||||
return True
|
return True
|
||||||
@@ -216,16 +209,10 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
for task in timer_tasks["timer_tasks"]:
|
for task in timer_tasks["timer_tasks"]:
|
||||||
task["add_time"] = datetime.strptime(task["add_time"], "%Y-%m-%d %H:%M:%S")
|
task["add_time"] = datetime.strptime(task["add_time"], "%Y-%m-%d %H:%M:%S")
|
||||||
task["execute_time"] = datetime.strptime(task["execute_time"], "%Y-%m-%d %H:%M:%S")
|
task["execute_time"] = datetime.strptime(task["execute_time"], "%Y-%m-%d %H:%M:%S")
|
||||||
task["status"] = TimerTaskStatus(task["status"])
|
task["status"] = ALTimerTaskStatus(task["status"])
|
||||||
return timer_tasks["timer_tasks"]
|
return timer_tasks["timer_tasks"]
|
||||||
raise Exception("定时任务配置文件格式错误")
|
raise Exception("定时任务配置文件格式错误")
|
||||||
except Exception as e:
|
except Exception:
|
||||||
QMessageBox.warning(
|
|
||||||
self,
|
|
||||||
"警告 - AutoLibrary",
|
|
||||||
f"加载定时任务配置发生错误 ! : {e}\n"\
|
|
||||||
f"文件路径: {timer_tasks_config_path}"
|
|
||||||
)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@@ -287,7 +274,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
):
|
):
|
||||||
|
|
||||||
self.hide()
|
self.hide()
|
||||||
self.timerTaskWidgetClosed.emit()
|
self.timerTaskManageWidgetClosed.emit()
|
||||||
event.ignore()
|
event.ignore()
|
||||||
|
|
||||||
|
|
||||||
@@ -297,17 +284,17 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
order: Qt.SortOrder = Qt.SortOrder.AscendingOrder
|
order: Qt.SortOrder = Qt.SortOrder.AscendingOrder
|
||||||
):
|
):
|
||||||
|
|
||||||
if policy == SortPolicy.BY_NAME:
|
if policy == self.SortPolicy.BY_NAME:
|
||||||
self.__timer_tasks.sort(
|
self.__timer_tasks.sort(
|
||||||
key = lambda x: x["name"],
|
key = lambda x: x["name"],
|
||||||
reverse = order is Qt.SortOrder.DescendingOrder
|
reverse = order is Qt.SortOrder.DescendingOrder
|
||||||
)
|
)
|
||||||
elif policy == SortPolicy.BY_ADD_TIME:
|
elif policy == self.SortPolicy.BY_ADD_TIME:
|
||||||
self.__timer_tasks.sort(
|
self.__timer_tasks.sort(
|
||||||
key = lambda x: x["add_time"],
|
key = lambda x: x["add_time"],
|
||||||
reverse = order is Qt.SortOrder.DescendingOrder
|
reverse = order is Qt.SortOrder.DescendingOrder
|
||||||
)
|
)
|
||||||
elif policy == SortPolicy.BY_EXECUTE_TIME:
|
elif policy == self.SortPolicy.BY_EXECUTE_TIME:
|
||||||
self.__timer_tasks.sort(
|
self.__timer_tasks.sort(
|
||||||
key = lambda x: x["execute_time"],
|
key = lambda x: x["execute_time"],
|
||||||
reverse = order is Qt.SortOrder.DescendingOrder
|
reverse = order is Qt.SortOrder.DescendingOrder
|
||||||
@@ -324,15 +311,15 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
invalid = 0
|
invalid = 0
|
||||||
total = len(self.__timer_tasks)
|
total = len(self.__timer_tasks)
|
||||||
for timer_task in self.__timer_tasks:
|
for timer_task in self.__timer_tasks:
|
||||||
if timer_task["status"] == TimerTaskStatus.PENDING:
|
if timer_task["status"] == ALTimerTaskStatus.PENDING:
|
||||||
pending += 1
|
pending += 1
|
||||||
elif timer_task["status"] == TimerTaskStatus.READY\
|
elif timer_task["status"] == ALTimerTaskStatus.READY\
|
||||||
or timer_task["status"] == TimerTaskStatus.RUNNING:
|
or timer_task["status"] == ALTimerTaskStatus.RUNNING:
|
||||||
in_queue += 1
|
in_queue += 1
|
||||||
elif timer_task["status"] == TimerTaskStatus.EXECUTED:
|
elif timer_task["status"] == ALTimerTaskStatus.EXECUTED:
|
||||||
executed += 1
|
executed += 1
|
||||||
elif timer_task["status"] == TimerTaskStatus.ERROR\
|
elif timer_task["status"] == ALTimerTaskStatus.ERROR\
|
||||||
or timer_task["status"] == TimerTaskStatus.OUTDATED:
|
or timer_task["status"] == ALTimerTaskStatus.OUTDATED:
|
||||||
invalid += 1
|
invalid += 1
|
||||||
self.TotalTaskLabel.setText(f"总任务:{total}")
|
self.TotalTaskLabel.setText(f"总任务:{total}")
|
||||||
self.PendingTaskLabel.setText(f"待执行:{pending}")
|
self.PendingTaskLabel.setText(f"待执行:{pending}")
|
||||||
@@ -350,7 +337,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
for timer_task in self.__timer_tasks:
|
for timer_task in self.__timer_tasks:
|
||||||
item = QListWidgetItem()
|
item = QListWidgetItem()
|
||||||
item.setData(Qt.UserRole, timer_task)
|
item.setData(Qt.UserRole, timer_task)
|
||||||
widget = TimerTaskItemWidget(self, timer_task)
|
widget = ALTimerTaskItemWidget(self, timer_task)
|
||||||
widget.DeleteButton.clicked.connect(
|
widget.DeleteButton.clicked.connect(
|
||||||
lambda _, uuid = timer_task["task_uuid"]: self.deleteTask(uuid)
|
lambda _, uuid = timer_task["task_uuid"]: self.deleteTask(uuid)
|
||||||
)
|
)
|
||||||
@@ -363,7 +350,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
self
|
self
|
||||||
):
|
):
|
||||||
|
|
||||||
dialog = ALAddTimerTaskWidget(self)
|
dialog = ALTimerTaskAddDialog(self)
|
||||||
if dialog.exec() == QDialog.DialogCode.Accepted:
|
if dialog.exec() == QDialog.DialogCode.Accepted:
|
||||||
timer_task = dialog.getTimerTask()
|
timer_task = dialog.getTimerTask()
|
||||||
self.__timer_tasks.append(timer_task)
|
self.__timer_tasks.append(timer_task)
|
||||||
@@ -398,8 +385,8 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
return
|
return
|
||||||
in_queue_tasks = [
|
in_queue_tasks = [
|
||||||
x for x in self.__timer_tasks
|
x for x in self.__timer_tasks
|
||||||
if x["status"] == TimerTaskStatus.READY
|
if x["status"] == ALTimerTaskStatus.READY
|
||||||
or x["status"] == TimerTaskStatus.RUNNING
|
or x["status"] == ALTimerTaskStatus.RUNNING
|
||||||
]
|
]
|
||||||
in_queue_count = len(in_queue_tasks)
|
in_queue_count = len(in_queue_tasks)
|
||||||
if in_queue_count > 0:
|
if in_queue_count > 0:
|
||||||
@@ -422,13 +409,13 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
for timer_task in self.__timer_tasks:
|
for timer_task in self.__timer_tasks:
|
||||||
if timer_task["execute_time"] > now:
|
if timer_task["execute_time"] > now:
|
||||||
continue
|
continue
|
||||||
if timer_task["status"] is not TimerTaskStatus.PENDING:
|
if timer_task["status"] is not ALTimerTaskStatus.PENDING:
|
||||||
continue
|
continue
|
||||||
if timer_task["execute_time"] <= now + timedelta(seconds = -5):
|
if timer_task["execute_time"] <= now + timedelta(seconds = -5):
|
||||||
timer_task["status"] = TimerTaskStatus.OUTDATED
|
timer_task["status"] = ALTimerTaskStatus.OUTDATED
|
||||||
need_update = True
|
need_update = True
|
||||||
else:
|
else:
|
||||||
timer_task["status"] = TimerTaskStatus.READY
|
timer_task["status"] = ALTimerTaskStatus.READY
|
||||||
self.timerTaskIsReady.emit(timer_task)
|
self.timerTaskIsReady.emit(timer_task)
|
||||||
need_update = True
|
need_update = True
|
||||||
if need_update:
|
if need_update:
|
||||||
@@ -441,9 +428,9 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
):
|
):
|
||||||
|
|
||||||
mapping = {
|
mapping = {
|
||||||
0: SortPolicy.BY_NAME,
|
0: self.SortPolicy.BY_NAME,
|
||||||
1: SortPolicy.BY_ADD_TIME,
|
1: self.SortPolicy.BY_ADD_TIME,
|
||||||
2: SortPolicy.BY_EXECUTE_TIME
|
2: self.SortPolicy.BY_EXECUTE_TIME
|
||||||
}
|
}
|
||||||
self.__sort_policy = mapping[policy]
|
self.__sort_policy = mapping[policy]
|
||||||
self.updateTimerTaskList()
|
self.updateTimerTaskList()
|
||||||
@@ -479,7 +466,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
|
|
||||||
for task in self.__timer_tasks:
|
for task in self.__timer_tasks:
|
||||||
if task["task_uuid"] == timer_task["task_uuid"]:
|
if task["task_uuid"] == timer_task["task_uuid"]:
|
||||||
task["status"] = TimerTaskStatus.RUNNING
|
task["status"] = ALTimerTaskStatus.RUNNING
|
||||||
self.timerTasksChanged.emit()
|
self.timerTasksChanged.emit()
|
||||||
|
|
||||||
|
|
||||||
@@ -491,7 +478,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
|
|
||||||
for task in self.__timer_tasks:
|
for task in self.__timer_tasks:
|
||||||
if task["task_uuid"] == timer_task["task_uuid"]:
|
if task["task_uuid"] == timer_task["task_uuid"]:
|
||||||
task["status"] = TimerTaskStatus.EXECUTED
|
task["status"] = ALTimerTaskStatus.EXECUTED
|
||||||
self.timerTasksChanged.emit()
|
self.timerTasksChanged.emit()
|
||||||
|
|
||||||
@Slot(dict)
|
@Slot(dict)
|
||||||
@@ -502,5 +489,5 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
|
|
||||||
for task in self.__timer_tasks:
|
for task in self.__timer_tasks:
|
||||||
if task["task_uuid"] == timer_task["task_uuid"]:
|
if task["task_uuid"] == timer_task["task_uuid"]:
|
||||||
task["status"] = TimerTaskStatus.ERROR
|
task["status"] = ALTimerTaskStatus.ERROR
|
||||||
self.timerTasksChanged.emit()
|
self.timerTasksChanged.emit()
|
||||||
@@ -21,7 +21,7 @@ from PySide6.QtGui import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TreeItemType(Enum):
|
class ALUserTreeItemType(Enum):
|
||||||
|
|
||||||
GROUP = 0
|
GROUP = 0
|
||||||
USER = 1
|
USER = 1
|
||||||
@@ -111,15 +111,15 @@ class ALUserTreeWidget(QTreeWidget):
|
|||||||
if source_item is None:
|
if source_item is None:
|
||||||
event.ignore()
|
event.ignore()
|
||||||
return
|
return
|
||||||
if source_item.type() == TreeItemType.GROUP.value:
|
if source_item.type() == ALUserTreeItemType.GROUP.value:
|
||||||
if target_item is not None:
|
if target_item is not None:
|
||||||
event.ignore()
|
event.ignore()
|
||||||
return
|
return
|
||||||
elif source_item.type() == TreeItemType.USER.value:
|
elif source_item.type() == ALUserTreeItemType.USER.value:
|
||||||
if target_item is None:
|
if target_item is None:
|
||||||
event.ignore()
|
event.ignore()
|
||||||
return
|
return
|
||||||
if target_item.type() != TreeItemType.GROUP.value:
|
if target_item.type() != ALUserTreeItemType.GROUP.value:
|
||||||
event.ignore()
|
event.ignore()
|
||||||
return
|
return
|
||||||
if target_item.checkState(1) == Qt.CheckState.Unchecked:
|
if target_item.checkState(1) == Qt.CheckState.Unchecked:
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
workflow process. Do not edit manually.
|
workflow process. Do not edit manually.
|
||||||
|
|
||||||
This file is auto-generated during the workflow process.
|
This file is auto-generated during the workflow process.
|
||||||
Last updated: 2026-01-17 17:51:55 UTC
|
Last updated: 2026-02-16 07:04:48 UTC
|
||||||
"""
|
"""
|
||||||
|
|
||||||
AL_VERSION = "1.0.3"
|
AL_VERSION = "1.0.5"
|
||||||
AL_TAG = "v1.0.3"
|
AL_TAG = "v1.0.5"
|
||||||
AL_COMMIT_SHA = "local"
|
AL_COMMIT_SHA = "local"
|
||||||
AL_COMMIT_DATE = "null" # time zone : UTC
|
AL_COMMIT_DATE = "null" # time zone : UTC
|
||||||
AL_BUILD_DATE = "null" # time zone : UTC
|
AL_BUILD_DATE = "null" # time zone : UTC
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
this folder is used to store the batch scripts.
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
this folder is used to store the config files.
|
|
||||||
|
Before Width: | Height: | Size: 785 KiB After Width: | Height: | Size: 785 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
@@ -104,7 +104,7 @@
|
|||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QFrame" name="frame">
|
<widget class="QFrame" name="AboutInfoSpaceFrame">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>56</width>
|
<width>56</width>
|
||||||
@@ -129,21 +129,24 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTextEdit" name="AboutInfoEdit">
|
<widget class="QTextBrowser" name="AboutInfoBrowser">
|
||||||
<property name="font">
|
<property name="frameShadow">
|
||||||
<font>
|
<enum>QFrame::Shadow::Plain</enum>
|
||||||
<family>Courier New</family>
|
</property>
|
||||||
<bold>false</bold>
|
<property name="verticalScrollBarPolicy">
|
||||||
</font>
|
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||||
|
</property>
|
||||||
|
<property name="horizontalScrollBarPolicy">
|
||||||
|
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="lineWrapMode">
|
<property name="lineWrapMode">
|
||||||
<enum>QTextEdit::LineWrapMode::NoWrap</enum>
|
<enum>QTextEdit::LineWrapMode::NoWrap</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="readOnly">
|
<property name="openExternalLinks">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="openLinks">
|
||||||
<set>Qt::TextInteractionFlag::TextBrowserInteraction</set>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -94,19 +94,19 @@
|
|||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="UserListLayout">
|
<layout class="QVBoxLayout" name="UserListLayout">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>5</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="topMargin">
|
<property name="topMargin">
|
||||||
<number>5</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="rightMargin">
|
<property name="rightMargin">
|
||||||
<number>5</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>5</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTreeWidget" name="UserTreeWidget">
|
<widget class="QTreeWidget" name="UserTreeWidget">
|
||||||
@@ -178,6 +178,9 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="UserListControlLayout">
|
<layout class="QHBoxLayout" name="UserListControlLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="DelUserButton">
|
<widget class="QPushButton" name="DelUserButton">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
@@ -309,7 +312,7 @@
|
|||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<layout class="QHBoxLayout" name="PasswordLayout">
|
<layout class="QHBoxLayout" name="PasswordLayout">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="PasswordEdit">
|
<widget class="QLineEdit" name="PasswordEdit">
|
||||||
@@ -546,7 +549,7 @@
|
|||||||
<item row="4" column="4">
|
<item row="4" column="4">
|
||||||
<layout class="QHBoxLayout" name="SeatIDLayout">
|
<layout class="QHBoxLayout" name="SeatIDLayout">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="SeatIDEdit">
|
<widget class="QLineEdit" name="SeatIDEdit">
|
||||||
@@ -703,7 +706,7 @@
|
|||||||
<item row="10" column="4">
|
<item row="10" column="4">
|
||||||
<layout class="QHBoxLayout" name="EndTimeDiffLayout">
|
<layout class="QHBoxLayout" name="EndTimeDiffLayout">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSpinBox" name="MaxEndTimeDiffSpinBox">
|
<widget class="QSpinBox" name="MaxEndTimeDiffSpinBox">
|
||||||
@@ -899,7 +902,7 @@
|
|||||||
<item row="7" column="4">
|
<item row="7" column="4">
|
||||||
<layout class="QHBoxLayout" name="BeginTimeDiffLayout">
|
<layout class="QHBoxLayout" name="BeginTimeDiffLayout">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSpinBox" name="MaxBeginTimeDiffSpinBox">
|
<widget class="QSpinBox" name="MaxBeginTimeDiffSpinBox">
|
||||||
@@ -1049,7 +1052,7 @@
|
|||||||
<item row="15" column="4">
|
<item row="15" column="4">
|
||||||
<layout class="QHBoxLayout" name="RenewTimeDiffLayout">
|
<layout class="QHBoxLayout" name="RenewTimeDiffLayout">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSpinBox" name="MaxRenewTimeDiffSpinBox">
|
<widget class="QSpinBox" name="MaxRenewTimeDiffSpinBox">
|
||||||
@@ -1092,7 +1095,7 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="15" column="1">
|
<item row="15" column="1">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="MaxRenewTimeDiffLabel">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>80</width>
|
<width>80</width>
|
||||||
@@ -1153,10 +1156,10 @@
|
|||||||
<property name="rightMargin">
|
<property name="rightMargin">
|
||||||
<number>3</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="horizontalSpacing">
|
<property name="bottomMargin">
|
||||||
<number>3</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="verticalSpacing">
|
<property name="spacing">
|
||||||
<number>5</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0" colspan="2">
|
<item row="0" column="0" colspan="2">
|
||||||
@@ -1353,7 +1356,7 @@
|
|||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>详情请参阅 <a href="https://www.autolibrary.cv/docs/manual_lists.html"><span style=" text-decoration: underline; color:#69fcff;">用户手册</span></a></p></body></html></string>
|
<string><html><head/><body><p>详情请参阅 <a href="https://www.autolibrary.top/manuals"><span style=" text-decoration: underline; color:#69fcff;">用户手册</span></a></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="whatsThis">
|
<property name="whatsThis">
|
||||||
<string><html><head/><body><p><br/></p></body></html></string>
|
<string><html><head/><body><p><br/></p></body></html></string>
|
||||||
@@ -1649,6 +1652,21 @@
|
|||||||
<string>当前配置</string>
|
<string>当前配置</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="CurrentConfigLayout">
|
<layout class="QGridLayout" name="CurrentConfigLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="spacing">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLineEdit" name="CurrentRunConfigEdit">
|
<widget class="QLineEdit" name="CurrentRunConfigEdit">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
@@ -1775,6 +1793,21 @@
|
|||||||
<string>导出路径</string>
|
<string>导出路径</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="ExportConfigLayout">
|
<layout class="QGridLayout" name="ExportConfigLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="spacing">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLineEdit" name="ExportUserConfigEdit">
|
<widget class="QLineEdit" name="ExportUserConfigEdit">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
@@ -34,13 +34,13 @@
|
|||||||
<number>5</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>3</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="topMargin">
|
<property name="topMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="rightMargin">
|
<property name="rightMargin">
|
||||||
<number>3</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
@@ -156,11 +156,9 @@
|
|||||||
<string><html><head/><body><p><br/></p></body></html></string>
|
<string><html><head/><body><p><br/></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="styleSheet">
|
<property name="styleSheet">
|
||||||
<string notr="true">background-color: rgb(10, 170, 10);
|
<string notr="true">background-color: #0AAA0A;
|
||||||
font: 12pt "Microsoft YaHei UI";
|
color: #FFFFFF;
|
||||||
color: rgb(255, 255, 255);
|
font: 700 9pt;</string>
|
||||||
font: 9pt "Segoe UI";
|
|
||||||
font: 700 9pt "Microsoft YaHei UI";</string>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>启动脚本</string>
|
<string>启动脚本</string>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ui version="4.0">
|
<ui version="4.0">
|
||||||
<class>ALAddTimerTaskDialog</class>
|
<class>ALTimerTaskAddDialog</class>
|
||||||
<widget class="QDialog" name="ALAddTimerTaskDialog">
|
<widget class="QDialog" name="ALTimerTaskAddDialog">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
@@ -86,16 +86,16 @@
|
|||||||
<number>5</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>5</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="topMargin">
|
<property name="topMargin">
|
||||||
<number>5</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="rightMargin">
|
<property name="rightMargin">
|
||||||
<number>5</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>5</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="TimerTypeSelectLayout">
|
<layout class="QHBoxLayout" name="TimerTypeSelectLayout">
|
||||||
@@ -135,16 +135,16 @@
|
|||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="TaskConfigLayout">
|
<layout class="QGridLayout" name="TaskConfigLayout">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>5</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="topMargin">
|
<property name="topMargin">
|
||||||
<number>5</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="rightMargin">
|
<property name="rightMargin">
|
||||||
<number>5</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>5</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>5</number>
|
<number>5</number>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ui version="4.0">
|
<ui version="4.0">
|
||||||
<class>ALTimerTaskWidget</class>
|
<class>ALTimerTaskManageWidget</class>
|
||||||
<widget class="QWidget" name="ALTimerTaskWidget">
|
<widget class="QWidget" name="ALTimerTaskManageWidget">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>定时任务 - AutoLibrary</string>
|
<string>定时任务管理 - AutoLibrary</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="ALTimerTaskWidgetLayout">
|
<layout class="QVBoxLayout" name="ALTimerTaskWidgetLayout">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
@@ -153,7 +153,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="styleSheet">
|
<property name="styleSheet">
|
||||||
<string notr="true">QLabel {
|
<string notr="true">QLabel {
|
||||||
color: #FF5722
|
color: #DC0000
|
||||||
}</string>
|
}</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -11,6 +11,7 @@ import os
|
|||||||
import queue
|
import queue
|
||||||
|
|
||||||
from selenium import webdriver
|
from selenium import webdriver
|
||||||
|
from selenium.common.exceptions import TimeoutException
|
||||||
from selenium.webdriver.common.by import By
|
from selenium.webdriver.common.by import By
|
||||||
from selenium.webdriver.support.ui import WebDriverWait
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
from selenium.webdriver.support import expected_conditions as EC
|
from selenium.webdriver.support import expected_conditions as EC
|
||||||
@@ -41,10 +42,11 @@ class AutoLib(MsgBase):
|
|||||||
self.__user_config = None
|
self.__user_config = None
|
||||||
self.__driver = None
|
self.__driver = None
|
||||||
if not self.__initBrowserDriver():
|
if not self.__initBrowserDriver():
|
||||||
raise Exception("浏览器驱动初始化失败")
|
raise Exception("浏览器驱动初始化失败 !")
|
||||||
else:
|
else:
|
||||||
if not self.__initDriverUrl():
|
if not self.__initDriverUrl():
|
||||||
raise Exception("浏览器驱动URL初始化失败")
|
self.close()
|
||||||
|
raise Exception("浏览器驱动URL初始化失败 !")
|
||||||
self.__initLibOperators()
|
self.__initLibOperators()
|
||||||
|
|
||||||
|
|
||||||
@@ -64,7 +66,8 @@ class AutoLib(MsgBase):
|
|||||||
case "firefox":
|
case "firefox":
|
||||||
driver_options = webdriver.FirefoxOptions()
|
driver_options = webdriver.FirefoxOptions()
|
||||||
case _:
|
case _:
|
||||||
raise Exception(f"不支持的浏览器驱动类型: {self.__driver_type} !")
|
self._showTrace(f"不支持的浏览器驱动类型: {self.__driver_type} !")
|
||||||
|
return False
|
||||||
|
|
||||||
if not web_driver_config:
|
if not web_driver_config:
|
||||||
self._showTrace("未配置浏览器驱动参数 !")
|
self._showTrace("未配置浏览器驱动参数 !")
|
||||||
@@ -107,7 +110,8 @@ class AutoLib(MsgBase):
|
|||||||
# init browser driver
|
# init browser driver
|
||||||
self.__driver_path = web_driver_config.get("driver_path")
|
self.__driver_path = web_driver_config.get("driver_path")
|
||||||
if not self.__driver_path:
|
if not self.__driver_path:
|
||||||
raise Exception(f"未配置浏览器驱动路径 !")
|
self._showTrace("未配置浏览器驱动路径 !")
|
||||||
|
return False
|
||||||
self.__driver_path = os.path.abspath(self.__driver_path)
|
self.__driver_path = os.path.abspath(self.__driver_path)
|
||||||
try:
|
try:
|
||||||
service = None
|
service = None
|
||||||
@@ -122,7 +126,8 @@ class AutoLib(MsgBase):
|
|||||||
self._showTrace(f"Firefox 浏览器驱动初始化略慢, 请耐心等待...")
|
self._showTrace(f"Firefox 浏览器驱动初始化略慢, 请耐心等待...")
|
||||||
service = FirefoxService(executable_path=self.__driver_path)
|
service = FirefoxService(executable_path=self.__driver_path)
|
||||||
self.__driver = webdriver.Firefox(service=service, options=driver_options)
|
self.__driver = webdriver.Firefox(service=service, options=driver_options)
|
||||||
case _:
|
case _: # actually will not happen, beacuse we have checked it at the initlization
|
||||||
|
# of 'driver_options'
|
||||||
raise Exception(f"不支持的浏览器驱动类型: {self.__driver_type}")
|
raise Exception(f"不支持的浏览器驱动类型: {self.__driver_type}")
|
||||||
self.__driver.implicitly_wait(1)
|
self.__driver.implicitly_wait(1)
|
||||||
self.__driver.execute_script(
|
self.__driver.execute_script(
|
||||||
@@ -183,10 +188,16 @@ class AutoLib(MsgBase):
|
|||||||
|
|
||||||
lib_config = self.__run_config.get("library", None)
|
lib_config = self.__run_config.get("library", None)
|
||||||
if not lib_config:
|
if not lib_config:
|
||||||
self._showError("未配置图书馆参数 !")
|
self._showTrace("未配置图书馆参数 !")
|
||||||
return False
|
return False
|
||||||
url = lib_config.get("host_url") + lib_config.get("login_url")
|
url = lib_config.get("host_url") + lib_config.get("login_url")
|
||||||
self.__driver.get(url)
|
self.__driver.set_page_load_timeout(5)
|
||||||
|
try:
|
||||||
|
self.__driver.get(url)
|
||||||
|
except TimeoutException:
|
||||||
|
self.__driver.execute_script("window.stop();")
|
||||||
|
self._showTrace(f"图书馆登录页面加载超时 ! 请检查网络环境是否正常")
|
||||||
|
return False
|
||||||
if not self.__waitResponseLoad():
|
if not self.__waitResponseLoad():
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -52,13 +52,13 @@ class ConfigReader:
|
|||||||
with open(self.__config_path, 'r', encoding='utf-8') as file:
|
with open(self.__config_path, 'r', encoding='utf-8') as file:
|
||||||
self.__config_data = json.load(file)
|
self.__config_data = json.load(file)
|
||||||
except FileNotFoundError as e:
|
except FileNotFoundError as e:
|
||||||
raise Exception(f"Config file not found: {self.__config_path}") from e
|
raise Exception(f"配置文件不存在: {self.__config_path}") from e
|
||||||
except PermissionError as e:
|
except PermissionError as e:
|
||||||
raise Exception(f"Without enough permission to read config file: {self.__config_path}") from e
|
raise Exception(f"没有足够的权限读取配置文件: {self.__config_path}") from e
|
||||||
except json.JSONDecodeError as e:
|
except json.JSONDecodeError as e:
|
||||||
raise Exception(f"JSON decode error in config file: {self.__config_path}") from e
|
raise Exception(f"JSON 解析错误: {self.__config_path}") from e
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise Exception(f"Unknown error occurred while reading config file: {e}") from e
|
raise Exception(f"读取配置文件时未知错误: {e}") from e
|
||||||
|
|
||||||
|
|
||||||
def getConfigs(
|
def getConfigs(
|
||||||
|
|||||||
@@ -58,13 +58,13 @@ class ConfigWriter:
|
|||||||
with open(self.__config_path, "w", encoding="utf-8") as f:
|
with open(self.__config_path, "w", encoding="utf-8") as f:
|
||||||
json.dump(self.__config_data, f, indent=4, sort_keys=False)
|
json.dump(self.__config_data, f, indent=4, sort_keys=False)
|
||||||
except PermissionError as e:
|
except PermissionError as e:
|
||||||
raise Exception(f"Without enough permission to write config file: {self.__config_path}") from e
|
raise Exception(f"没有足够的权限写入配置文件: {self.__config_path}") from e
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
raise Exception(f"IO error occurred while writing config file: {self.__config_path}") from e
|
raise Exception(f"写入配置文件时发生 IO 错误: {self.__config_path}") from e
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
raise Exception(f"Config data contains invalid type that can not be JSON serialized: {e}") from e
|
raise Exception(f"配置数据包含无法 JSON 序列化的类型: {e}") from e
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise Exception(f"Unknown error occurred while writing config file: {e}") from e
|
raise Exception(f"写入配置文件时未知错误: {e}") from e
|
||||||
|
|
||||||
|
|
||||||
def setConfigs(
|
def setConfigs(
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
This folder is used to store the template config files.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"library": {
|
||||||
|
"host_url": "http://10.1.20.7",
|
||||||
|
"login_url": "/login"
|
||||||
|
},
|
||||||
|
"login": {
|
||||||
|
"auto_captcha": true,
|
||||||
|
"max_attempt": 3
|
||||||
|
},
|
||||||
|
"web_driver": {
|
||||||
|
"driver_type": "edge",
|
||||||
|
"driver_path": "",
|
||||||
|
"headless": false
|
||||||
|
},
|
||||||
|
"mode": {
|
||||||
|
"run_mode": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"groups": []
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
This folder is used to store the template files.
|
||||||
|
|
||||||
|
Directory structure:
|
||||||
|
|
||||||
|
templates
|
||||||
|
|─── configs // template config files
|
||||||
Reference in New Issue
Block a user