mirror of
https://github.com/KenanZhu/AutoLibrary.git
synced 2026-06-18 07:23:03 +08:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 149910d628 | |||
| 2a7ed099bf | |||
| 473f32ca29 | |||
| 580052f1e3 | |||
| 6abf530307 | |||
| 577c651ef8 | |||
| 18ae949900 | |||
| ca9059d1db | |||
| ad4deae0c6 |
@@ -1,5 +1,112 @@
|
|||||||
|
|
||||||
# AutoLibrary
|
# AutoLibrary
|
||||||
|
---
|
||||||
|
|
||||||
请访问[AutoLibrary 网站](http://autolibrary.cv)\
|

|
||||||
Please access the [AutoLibrary Website](http://autolibrary.cv)
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
了解更多请访问 [_AutoLibrary 网站_](http://autolibrary.cv)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 功能
|
||||||
|
|
||||||
|
1. 自动预约 - 支持自动预约
|
||||||
|
2. 自动续约 - 支持自动续约
|
||||||
|
3. 自动签到 - 支持自动签到
|
||||||
|
4. 批量操作 - 支持同时预约多个用户,可以指定当前需要跳过的用户,并将用户分成多个组
|
||||||
|
5. 定时任务 - 使用内置定时任务管理,添加定时任务,指定时间后按当前预约信息自动运行
|
||||||
|
|
||||||
|
_1,2,3 的具体操作方法和注意事项请访问网站 [帮助手册](https://autolibrary.cv/docs/manual_lists.html)_
|
||||||
|
|
||||||
|
### 特点
|
||||||
|
|
||||||
|
#### 关于预约等操作的注意事项
|
||||||
|
|
||||||
|
工具会自动处理登录过程的验证码识别过程,正常情况下单次识别准确率在 90% 以上,如遇验证码识别错误,大概率是校园网网络环境不佳导致的。
|
||||||
|
|
||||||
|
只要确保处于校园网网络环境内,工具都是可以正常运行的。操作处理速度基本上取决于校园网的网络环境,一般情况下在 3-4 秒左右即可完成一个用户的操作,完全满足正常使用需求。
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> 工具仅作为正常的预约,签到和续约的图书馆辅助工具,请勿干扰图书馆的正常运行(如故意预约多个座位,或同时预约大量的用户等,对此影响图书馆正常运行本工具概不负责,请在善用工具方便自己的情况下尽量不用影响其他同学的使用)。
|
||||||
|
|
||||||
|
#### 关于批量操作的注意事项
|
||||||
|
|
||||||
|
批量操作时,建议将需要操作的用户分成多个组,每个组的用户数量不要超过 4 人(即一整张桌子的数量),否则会影响操作效率,大量用户同时预约会一定程度上增加图书馆服务器的压力,影响正常使用。根据需要在用户管理界面中可以勾选本次操作是否跳过该用户,以提高运行效率。
|
||||||
|
|
||||||
|
#### 关于定时任务的注意事项
|
||||||
|
|
||||||
|
定时任务会在指定的时间自动运行,运行时会根据当前预约信息进行操作。一般情况下不建议设置两个运行开始时间比较接近的定时任务,否则后一个任务会等待前一个任务完成后才会运行,按照队列的顺序执行。
|
||||||
|
|
||||||
|
### 如何使用
|
||||||
|
|
||||||
|
1. 下载最新版本的 AutoLibrary 工具压缩包,[点击这里](https://github.com/KenanZhu/AutoLibrary/releases)。
|
||||||
|
2. 解压下载的文件到任意目录。
|
||||||
|
3. 运行 `AutoLibrary.exe` 文件。
|
||||||
|
4. 按照提示操作即可。
|
||||||
|
|
||||||
|
#### 平台支持 & 编译步骤
|
||||||
|
|
||||||
|
本工具目前仅支持 Windows 平台,由于使用 PySide6 库开发,理论上是可以自行编译并在 Linux 和 macOS 上运行,这里提供简单的编译步骤:
|
||||||
|
|
||||||
|
1. 确保系统安装了 Python 3.13 或以上版本。
|
||||||
|
2. 安装 pyside6 selenium ddddocr 库,命令为 `pip install pyside6 selenium ddddocr`。
|
||||||
|
3. 在 `src/gui/batchs` 目录下运行 `complie_ui.bat` (linux 和 macOS 系统使用 `complie_ui.sh`) 文件来编译 Qt 的 UI 文件。
|
||||||
|
4. 在上一步相同目录内运行 `complie_rc.bat` (linux 和 macOS 系统使用 `complie_rc.sh`) 文件来编译 Qt 的资源文件。
|
||||||
|
5. 待上述步骤完成后,运行 `src/Main.py` 文件即可。
|
||||||
|
|
||||||
|
*注意 1*:如果 python 使用的是虚拟环境,请在虚拟环境安装依赖后,在激活的虚拟环境终端中使用 `cd src/gui/batchs` 命令切换到 `batchs` 目录下,再运行编译脚本。否则会提示缺少必要的 Qt PySide 依赖库。
|
||||||
|
|
||||||
|
*注意 2*:由于 ddddocr 的代码版本问题,其中的 `__init__.py` 文件中的函数 `def classification(self, img: bytes):` 中的 `image.resize` 方法传入了不符合当前版本的`resample` 参数,导致在 Python 3.13 以上中运行时会报错。请将 `image.resize` 方法中的参数替换为 `resample=Image.Resampling.LANCZOS`,具体函数如下:
|
||||||
|
```python
|
||||||
|
def classification(self, img: bytes):
|
||||||
|
image = Image.open(io.BytesIO(img))
|
||||||
|
image = image.resize((int(image.size[0]*(64/image.size[1])), 64), Image.Resampling.LANCZOS).convert('L')
|
||||||
|
^^^^^
|
||||||
|
请将上述参数替换为如上所示的 `Image.Resampling.LANCZOS`
|
||||||
|
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q&A
|
||||||
|
|
||||||
|
#### 为什么开发这个工具?
|
||||||
|
|
||||||
|
其实是因为自己在使用图书馆时,发现预约和续约等操作比较麻烦,图书馆的登录系统也比较老旧,验证码错误后需要重复输入。有时候网络环境不好的时候,登录很慢,想赶紧签到或者预约明天的座位,而且会有朋友让我帮忙预约一个座位,这时候就需要一个工具来帮助自己快速完成这些操作,自己则不需要管这些事情,只需要专注自己的事情就可以了。
|
||||||
|
|
||||||
|
#### 工具后续会收费吗?
|
||||||
|
|
||||||
|
不会,本工具完全免费使用,也不会有任何收费项,如果你觉工具对你有帮助,可以为我捐助一瓶可乐的价格,以用于 AutoLibrary 网站的维护和软件的稳定更新。
|
||||||
|
|
||||||
|
#### 会有手机端的版本吗?
|
||||||
|
|
||||||
|
暂时没有考虑,而且也没有足够的能力和精力开发多平台的版本并维护,所以暂时只提供 Windows 版本。
|
||||||
|
|
||||||
|
#### 后续会有哪些功能?
|
||||||
|
|
||||||
|
由于本人的时间和精力有限,开发后续功能会有所取舍,如果你有什么功能建议或者想参与开发,欢迎联系我。
|
||||||
|
|
||||||
|
首先当前 1.0.0 版本的功能对于正常使用已经足够,不过会考虑后续着重完善 2-4 预约时的操作流程,暂时由以下构想:
|
||||||
|
|
||||||
|
1. 2-4 人一起预约时,往往会偏向于预约并排或对面的整个空座位,这时候工具会按照一定策略查询搜索符合条件的座位,并预约并排或对面的整个座位,而不是各自独立预约。
|
||||||
|
2. 预约时会考虑到组内用户的预约时间是否冲突,若冲突则会提示用户是否继续预约,若用户选择继续预约,则会按需要调整预约时间,再进行预约。
|
||||||
|
3. 对于比较固定的用户,会考虑在定时任务管理中添加如 ‘每日任务’ ‘每周任务’ 等选项,用户可以根据需要设置定时任务重复的日期范围,自动完成预约,签到,续约等操作。
|
||||||
|
|
||||||
|
不过以上功能的实现,需要一定的时间和精力测试与调试,也需要考虑到图书馆的正常运行,所以暂时不会着手开发,也许会进行一些小的功能验证。
|
||||||
|
|
||||||
|
#### 其他功能建议?
|
||||||
|
|
||||||
|
如果有其他功能建议,或者遇到了什么功能性,操作上的问题,欢迎联系我。
|
||||||
|
|
||||||
|
如果你有足够的开发能力,可以 Fork 本项目,根据自己的需求进行修改和完善,也欢迎提交 Pull Request 到本项目。
|
||||||
|
|
||||||
|
### 联系我
|
||||||
|
|
||||||
|
- 项目维护:[KenanZhu (Nanoki)](https://github.com/KenanZhu)
|
||||||
|
- 电子邮箱:<nanoki_zh@163.com>
|
||||||
|
|
||||||
|
_**Free to use** —— AutoLibrary 是一个基于 MIT 协议免费开源的工具_
|
||||||
|
|||||||
+2
-2
@@ -29,7 +29,7 @@ class MsgBase:
|
|||||||
msg: str
|
msg: str
|
||||||
):
|
):
|
||||||
|
|
||||||
self._output_queue.put(f"[{self._class_name:<12}] >>> : {msg}")
|
self._output_queue.put(f"[{self._class_name:<15}] >>> : {msg}")
|
||||||
|
|
||||||
|
|
||||||
def _showTrace(
|
def _showTrace(
|
||||||
@@ -38,7 +38,7 @@ class MsgBase:
|
|||||||
):
|
):
|
||||||
|
|
||||||
timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||||
self._output_queue.put(f"{timestamp}-[{self._class_name:<12}] : {msg}")
|
self._output_queue.put(f"{timestamp}-[{self._class_name:<15}] : {msg}")
|
||||||
|
|
||||||
|
|
||||||
def _waitMsg(
|
def _waitMsg(
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class ALAboutDialog(QDialog, Ui_ALAboutDialog):
|
|||||||
self
|
self
|
||||||
):
|
):
|
||||||
|
|
||||||
self.LogoIconLabel.setPixmap(QIcon(":/res/icon/icons/AutoLibrary.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.AboutInfoEdit.setHtml(info_text)
|
||||||
self.AboutInfoEdit.setTextInteractionFlags(Qt.TextBrowserInteraction)
|
self.AboutInfoEdit.setTextInteractionFlags(Qt.TextBrowserInteraction)
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ class TimerTaskStatus(Enum):
|
|||||||
READY = "已就绪"
|
READY = "已就绪"
|
||||||
RUNNING = "执行中"
|
RUNNING = "执行中"
|
||||||
EXECUTED = "已执行"
|
EXECUTED = "已执行"
|
||||||
|
ERROR = "执行失败"
|
||||||
OUTDATED = "已过期"
|
OUTDATED = "已过期"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+18
-18
@@ -38,6 +38,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
|
|
||||||
timerTaskIsRunning = Signal(dict)
|
timerTaskIsRunning = Signal(dict)
|
||||||
timerTaskIsExecuted = Signal(dict)
|
timerTaskIsExecuted = Signal(dict)
|
||||||
|
timerTaskIsError = Signal(dict)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self
|
self
|
||||||
@@ -74,7 +75,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
self
|
self
|
||||||
):
|
):
|
||||||
|
|
||||||
self.icon = QIcon(":/res/icon/icons/AutoLibrary.ico")
|
self.icon = QIcon(":/res/icon/icons/AutoLibrary_32x32.ico")
|
||||||
self.setWindowIcon(self.icon)
|
self.setWindowIcon(self.icon)
|
||||||
self.MessageIOTextEdit.setFont(QFont("Courier New", 10))
|
self.MessageIOTextEdit.setFont(QFont("Courier New", 10))
|
||||||
self.ManualAction.triggered.connect(self.onManualActionTriggered)
|
self.ManualAction.triggered.connect(self.onManualActionTriggered)
|
||||||
@@ -84,6 +85,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
self.__alTimerTaskWidget = ALTimerTaskWidget(self, self.__config_paths["timer_task"])
|
self.__alTimerTaskWidget = ALTimerTaskWidget(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.__alTimerTaskWidget.timerTaskIsReady.connect(self.onTimerTaskIsReady)
|
self.__alTimerTaskWidget.timerTaskIsReady.connect(self.onTimerTaskIsReady)
|
||||||
self.__alTimerTaskWidget.timerTaskWidgetClosed.connect(self.onTimerTaskWidgetClosed)
|
self.__alTimerTaskWidget.timerTaskWidgetClosed.connect(self.onTimerTaskWidgetClosed)
|
||||||
self.__alTimerTaskWidget.setWindowFlags(Qt.WindowType.Window|Qt.WindowType.WindowCloseButtonHint)
|
self.__alTimerTaskWidget.setWindowFlags(Qt.WindowType.Window|Qt.WindowType.WindowCloseButtonHint)
|
||||||
@@ -229,7 +231,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(False, False, True)
|
self.setControlButtons(True, True, False)
|
||||||
if not timer_task["silent"]:
|
if not timer_task["silent"]:
|
||||||
self.TrayIcon.showMessage(
|
self.TrayIcon.showMessage(
|
||||||
"定时任务 - AutoLibrary",
|
"定时任务 - AutoLibrary",
|
||||||
@@ -245,8 +247,6 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
self.__config_paths
|
self.__config_paths
|
||||||
)
|
)
|
||||||
self.__current_timer_task_thread.finishedSignal_TimerWorker.connect(self.onTimerTaskFinished)
|
self.__current_timer_task_thread.finishedSignal_TimerWorker.connect(self.onTimerTaskFinished)
|
||||||
self.__current_timer_task_thread.showTraceSignal.connect(self.showTrace)
|
|
||||||
self.__current_timer_task_thread.showMsgSignal.connect(self.showMsg)
|
|
||||||
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
|
||||||
@@ -270,7 +270,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
msg: str
|
msg: str
|
||||||
):
|
):
|
||||||
|
|
||||||
self.appendToTextEdit(f"[{self.__class_name:<12}] >>> : {msg}")
|
self.__output_queue.put(f"[{self.__class_name:<15}] >>> : {msg}")
|
||||||
|
|
||||||
@Slot()
|
@Slot()
|
||||||
def showTrace(
|
def showTrace(
|
||||||
@@ -279,7 +279,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
):
|
):
|
||||||
|
|
||||||
timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||||
self.appendToTextEdit(f"{timestamp}-[{self.__class_name:<12}] : {msg}")
|
self.__output_queue.put(f"{timestamp}-[{self.__class_name:<15}] : {msg}")
|
||||||
|
|
||||||
@Slot()
|
@Slot()
|
||||||
def pollMsgQueue(
|
def pollMsgQueue(
|
||||||
@@ -293,7 +293,6 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@Slot()
|
@Slot()
|
||||||
def onTimerTaskWidgetClosed(
|
def onTimerTaskWidgetClosed(
|
||||||
self
|
self
|
||||||
@@ -301,7 +300,6 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
|
|
||||||
self.TimerTaskWidgetButton.setEnabled(True)
|
self.TimerTaskWidgetButton.setEnabled(True)
|
||||||
|
|
||||||
|
|
||||||
@Slot(dict)
|
@Slot(dict)
|
||||||
def onConfigWidgetClosed(
|
def onConfigWidgetClosed(
|
||||||
self,
|
self,
|
||||||
@@ -326,13 +324,12 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
@Slot(dict)
|
@Slot(dict)
|
||||||
def onTimerTaskFinished(
|
def onTimerTaskFinished(
|
||||||
self,
|
self,
|
||||||
|
is_error: bool,
|
||||||
timer_task: dict
|
timer_task: dict
|
||||||
):
|
):
|
||||||
|
|
||||||
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.finishedSignal_TimerWorker.disconnect(self.onTimerTaskFinished)
|
||||||
self.__current_timer_task_thread.showTraceSignal.disconnect(self.showTrace)
|
|
||||||
self.__current_timer_task_thread.showMsgSignal.disconnect(self.showMsg)
|
|
||||||
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(True, False, True)
|
self.setControlButtons(True, False, True)
|
||||||
@@ -341,12 +338,17 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
timer_task["executed"] = True
|
timer_task["executed"] = True
|
||||||
self.TrayIcon.showMessage(
|
self.TrayIcon.showMessage(
|
||||||
"定时任务 - AutoLibrary",
|
"定时任务 - AutoLibrary",
|
||||||
f"\n定时任务 '{timer_task['name']}' 执行完成",
|
f"\n定时任务 '{timer_task['name']}' 执行{'失败' if is_error else '完成'}",
|
||||||
QSystemTrayIcon.MessageIcon.Information,
|
QSystemTrayIcon.MessageIcon.Information,
|
||||||
1000
|
1000
|
||||||
)
|
)
|
||||||
self.showTrace(f"定时任务 {timer_task['name']} 执行完成, uuid: {timer_task['task_uuid']}")
|
self.showTrace(
|
||||||
self.timerTaskIsExecuted.emit(timer_task)
|
f"定时任务 {timer_task['name']} 执行{'失败' if is_error else '完成'}, uuid: {timer_task['task_uuid']}"
|
||||||
|
)
|
||||||
|
if not is_error:
|
||||||
|
self.timerTaskIsExecuted.emit(timer_task)
|
||||||
|
else:
|
||||||
|
self.timerTaskIsError.emit(timer_task)
|
||||||
|
|
||||||
@Slot()
|
@Slot()
|
||||||
def onTimerTaskWidgetButtonClicked(
|
def onTimerTaskWidgetButtonClicked(
|
||||||
@@ -379,7 +381,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
self
|
self
|
||||||
):
|
):
|
||||||
|
|
||||||
self.setControlButtons(False, False, True)
|
self.setControlButtons(True, 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,
|
||||||
@@ -387,8 +389,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
self.__config_paths
|
self.__config_paths
|
||||||
)
|
)
|
||||||
self.__auto_lib_thread.finishedSignal.connect(self.onStopButtonClicked)
|
self.__auto_lib_thread.finishedSignal.connect(self.onStopButtonClicked)
|
||||||
self.__auto_lib_thread.showMsgSignal.connect(self.showMsg)
|
self.__auto_lib_thread.finishedWithErrorSignal.connect(self.onStopButtonClicked)
|
||||||
self.__auto_lib_thread.showTraceSignal.connect(self.showTrace)
|
|
||||||
self.__auto_lib_thread.start()
|
self.__auto_lib_thread.start()
|
||||||
|
|
||||||
@Slot()
|
@Slot()
|
||||||
@@ -400,9 +401,8 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
|||||||
self.showTrace("正在停止操作......")
|
self.showTrace("正在停止操作......")
|
||||||
self.__auto_lib_thread.wait(2000)
|
self.__auto_lib_thread.wait(2000)
|
||||||
self.showTrace("操作已停止")
|
self.showTrace("操作已停止")
|
||||||
self.__auto_lib_thread.showMsgSignal.disconnect(self.showMsg)
|
|
||||||
self.__auto_lib_thread.showTraceSignal.disconnect(self.showTrace)
|
|
||||||
self.__auto_lib_thread.finishedSignal.disconnect(self.onStopButtonClicked)
|
self.__auto_lib_thread.finishedSignal.disconnect(self.onStopButtonClicked)
|
||||||
|
self.__auto_lib_thread.finishedWithErrorSignal.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(True, False, True)
|
self.setControlButtons(True, False, True)
|
||||||
|
|||||||
+48
-53
@@ -12,18 +12,18 @@ import time
|
|||||||
import queue
|
import queue
|
||||||
|
|
||||||
from PySide6.QtCore import (
|
from PySide6.QtCore import (
|
||||||
Signal, QThread
|
Slot, Signal, QThread
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from base.MsgBase import MsgBase
|
||||||
from operators.AutoLib import AutoLib
|
from operators.AutoLib import AutoLib
|
||||||
from utils.ConfigReader import ConfigReader
|
from utils.ConfigReader import ConfigReader
|
||||||
|
|
||||||
|
|
||||||
class AutoLibWorker(QThread):
|
class AutoLibWorker(QThread, MsgBase):
|
||||||
|
|
||||||
finishedSignal = Signal()
|
finishedSignal = Signal()
|
||||||
showTraceSignal = Signal(str)
|
finishedWithErrorSignal = Signal()
|
||||||
showMsgSignal = Signal(str)
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -32,10 +32,8 @@ class AutoLibWorker(QThread):
|
|||||||
config_paths: dict
|
config_paths: dict
|
||||||
):
|
):
|
||||||
|
|
||||||
super().__init__()
|
super().__init__(input_queue = input_queue, output_queue = output_queue)
|
||||||
|
|
||||||
self.__input_queue = input_queue
|
|
||||||
self.__output_queue = output_queue
|
|
||||||
self.__config_paths = config_paths
|
self.__config_paths = config_paths
|
||||||
|
|
||||||
|
|
||||||
@@ -45,6 +43,10 @@ class AutoLibWorker(QThread):
|
|||||||
|
|
||||||
current_time = time.strftime("%H:%M", time.localtime())
|
current_time = time.strftime("%H:%M", time.localtime())
|
||||||
if current_time >= "23:30" or current_time <= "07:30":
|
if current_time >= "23:30" or current_time <= "07:30":
|
||||||
|
self._showTrace(
|
||||||
|
"当前时间不在图书馆开放时间内\n"\
|
||||||
|
" 请在 07:30 - 23:30 之间尝试"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -56,9 +58,7 @@ class AutoLibWorker(QThread):
|
|||||||
if not all(
|
if not all(
|
||||||
os.path.exists(path) for path in self.__config_paths.values()
|
os.path.exists(path) for path in self.__config_paths.values()
|
||||||
):
|
):
|
||||||
self.showTraceSignal.emit(
|
self._showTrace("配置文件路径不存在, 请检查配置文件路径是否正确。")
|
||||||
"配置文件路径不存在, 请检查配置文件路径是否正确。"
|
|
||||||
)
|
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -67,25 +67,24 @@ class AutoLibWorker(QThread):
|
|||||||
self
|
self
|
||||||
) -> bool:
|
) -> bool:
|
||||||
|
|
||||||
self.showTraceSignal.emit(
|
self._showTrace(
|
||||||
f"正在加载配置文件, 运行配置文件路径: {self.__config_paths["run"]}"
|
f"正在加载配置文件, 运行配置文件路径: {self.__config_paths["run"]}"
|
||||||
)
|
)
|
||||||
self.__run_config = ConfigReader(
|
self.__run_config = ConfigReader(
|
||||||
self.__config_paths["run"]
|
self.__config_paths["run"]
|
||||||
).getConfigs()
|
).getConfigs()
|
||||||
self.showTraceSignal.emit(
|
self._showTrace(
|
||||||
f"正在加载配置文件, 用户配置文件路径: {self.__config_paths["user"]}"
|
f"正在加载配置文件, 用户配置文件路径: {self.__config_paths["user"]}"
|
||||||
)
|
)
|
||||||
self.__user_config = ConfigReader(
|
self.__user_config = ConfigReader(
|
||||||
self.__config_paths["user"]
|
self.__config_paths["user"]
|
||||||
).getConfigs()
|
).getConfigs()
|
||||||
if self.__run_config is None or self.__user_config is None:
|
if self.__run_config is None or self.__user_config is None:
|
||||||
self.showTraceSignal.emit(
|
self._showTrace("配置文件加载失败, 请检查配置文件是否正确")
|
||||||
"配置文件加载失败, 请检查配置文件是否正确。"
|
self._showTrace("配置文件加载失败, 请检查配置文件是否正确")
|
||||||
)
|
|
||||||
return False
|
return False
|
||||||
if not self.__user_config.get("groups"):
|
if not self.__user_config.get("groups"):
|
||||||
self.showTraceSignal.emit(
|
self._showTrace(
|
||||||
"用户配置文件中无有效任务组, 请检查用户配置文件是否正确"
|
"用户配置文件中无有效任务组, 请检查用户配置文件是否正确"
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
@@ -99,55 +98,39 @@ class AutoLibWorker(QThread):
|
|||||||
auto_lib = None
|
auto_lib = None
|
||||||
try:
|
try:
|
||||||
if not self.checkTimeAvailable():
|
if not self.checkTimeAvailable():
|
||||||
self.showTraceSignal.emit(
|
|
||||||
"当前时间不在图书馆开放时间内\n"\
|
|
||||||
" 请在 07:30 - 23:30 之间尝试"
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
if not self.checkConfigPaths():
|
if not self.checkConfigPaths():
|
||||||
return
|
return
|
||||||
self.showTraceSignal.emit("AutoLibrary 开始运行")
|
self._showTrace("AutoLibrary 开始运行")
|
||||||
if not self.loadConfigs():
|
if not self.loadConfigs():
|
||||||
return
|
raise Exception("配置文件加载失败")
|
||||||
auto_lib = AutoLib(
|
auto_lib = AutoLib(
|
||||||
self.__input_queue,
|
self._input_queue,
|
||||||
self.__output_queue,
|
self._output_queue,
|
||||||
self.__run_config
|
self.__run_config
|
||||||
)
|
)
|
||||||
if auto_lib is None:
|
|
||||||
self.showTraceSignal.emit(
|
|
||||||
"AutoLibrary 初始化失败"
|
|
||||||
)
|
|
||||||
return
|
|
||||||
groups = self.__user_config.get("groups")
|
groups = self.__user_config.get("groups")
|
||||||
for group in groups:
|
for group in groups:
|
||||||
time.sleep(0.2) # wait for the message queue to be empty
|
|
||||||
if not group["enabled"]:
|
if not group["enabled"]:
|
||||||
self.showTraceSignal.emit(
|
self._showTrace(f"任务组 {group["name"]} 已跳过")
|
||||||
f"任务组 {group["name"]} 已跳过"
|
|
||||||
)
|
|
||||||
continue
|
continue
|
||||||
self.showTraceSignal.emit(
|
self._showTrace(f"正在运行任务组 {group["name"]}")
|
||||||
f"正在运行任务组 {group["name"]}"
|
|
||||||
)
|
|
||||||
auto_lib.run(
|
auto_lib.run(
|
||||||
{ "users": group.get("users", []) }
|
{ "users": group.get("users", []) }
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.showTraceSignal.emit(
|
self._showTrace(f"AutoLibrary 运行时发生异常 : {e}")
|
||||||
f"AutoLibrary 运行时发生异常 : {e}"
|
self.finishedWithErrorSignal.emit()
|
||||||
)
|
return
|
||||||
finally:
|
if auto_lib:
|
||||||
if auto_lib:
|
auto_lib.close()
|
||||||
auto_lib.close()
|
self._showTrace("AutoLibrary 运行结束")
|
||||||
time.sleep(0.2) # wait for the message queue to be empty
|
self.finishedSignal.emit()
|
||||||
self.showTraceSignal.emit("AutoLibrary 运行结束")
|
|
||||||
self.finishedSignal.emit()
|
|
||||||
|
|
||||||
|
|
||||||
class TimerTaskWorker(AutoLibWorker):
|
class TimerTaskWorker(AutoLibWorker):
|
||||||
|
|
||||||
finishedSignal_TimerWorker = Signal(dict)
|
finishedSignal_TimerWorker = Signal(bool, dict)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -160,16 +143,28 @@ 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.finishedWithErrorSignal.connect(self.onTimerTaskIsError)
|
||||||
|
|
||||||
def run(
|
def run(
|
||||||
self
|
self
|
||||||
):
|
):
|
||||||
|
|
||||||
self.showTraceSignal.emit(
|
self._showTrace(f"定时任务 {self.__timer_task['name']} 开始运行")
|
||||||
f"定时任务 {self.__timer_task['name']} 开始运行"
|
|
||||||
)
|
|
||||||
super().run()
|
super().run()
|
||||||
self.showTraceSignal.emit(
|
|
||||||
f"定时任务 {self.__timer_task['name']} 运行结束"
|
@Slot(dict)
|
||||||
)
|
def onTimerTaskIsError(
|
||||||
self.finishedSignal_TimerWorker.emit(self.__timer_task)
|
self
|
||||||
|
):
|
||||||
|
|
||||||
|
self._showTrace(f"定时任务 {self.__timer_task['name']} 运行时发生异常")
|
||||||
|
self.finishedSignal_TimerWorker.emit(True, self.__timer_task)
|
||||||
|
|
||||||
|
@Slot(dict)
|
||||||
|
def onTimerTaskIsFinished(
|
||||||
|
self
|
||||||
|
):
|
||||||
|
|
||||||
|
self._showTrace(f"定时任务 {self.__timer_task['name']} 运行结束")
|
||||||
|
self.finishedSignal_TimerWorker.emit(False, self.__timer_task)
|
||||||
|
|||||||
@@ -94,6 +94,9 @@ class TimerTaskItemWidget(QWidget):
|
|||||||
case TimerTaskStatus.EXECUTED:
|
case TimerTaskStatus.EXECUTED:
|
||||||
TaskStatusText = "已执行"
|
TaskStatusText = "已执行"
|
||||||
TaskStatusColor = "#4CAF50"
|
TaskStatusColor = "#4CAF50"
|
||||||
|
case TimerTaskStatus.ERROR:
|
||||||
|
TaskStatusText = "执行失败"
|
||||||
|
TaskStatusColor = "#FF5722"
|
||||||
case TimerTaskStatus.OUTDATED:
|
case TimerTaskStatus.OUTDATED:
|
||||||
TaskStatusText = "已过期"
|
TaskStatusText = "已过期"
|
||||||
TaskStatusColor = "#FF5722"
|
TaskStatusColor = "#FF5722"
|
||||||
@@ -151,6 +154,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
self.__timer_tasks = []
|
self.__timer_tasks = []
|
||||||
self.__check_timer = None
|
self.__check_timer = None
|
||||||
self.__sort_policy = SortPolicy.BY_EXECUTE_TIME
|
self.__sort_policy = SortPolicy.BY_EXECUTE_TIME
|
||||||
|
self.__sort_order = Qt.SortOrder.AscendingOrder
|
||||||
self.__timer_tasks_config_path = timer_tasks_config_path
|
self.__timer_tasks_config_path = timer_tasks_config_path
|
||||||
|
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
@@ -167,6 +171,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
self.AddTimerTaskButton.clicked.connect(self.addTask)
|
self.AddTimerTaskButton.clicked.connect(self.addTask)
|
||||||
self.ClearAllTimerTasksButton.clicked.connect(self.clearAllTasks)
|
self.ClearAllTimerTasksButton.clicked.connect(self.clearAllTasks)
|
||||||
self.TimerTaskSortTypeComboBox.currentIndexChanged.connect(self.onSortPolicyComboBoxChanged)
|
self.TimerTaskSortTypeComboBox.currentIndexChanged.connect(self.onSortPolicyComboBoxChanged)
|
||||||
|
self.TimerTaskSortOrderToggleButton.clicked.connect(self.onSortOrderToggleButtonClicked)
|
||||||
self.timerTasksChanged.connect(self.onTimerTasksChanged)
|
self.timerTasksChanged.connect(self.onTimerTasksChanged)
|
||||||
|
|
||||||
|
|
||||||
@@ -291,20 +296,24 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
|
|
||||||
def sortTimerTasks(
|
def sortTimerTasks(
|
||||||
self,
|
self,
|
||||||
policy: SortPolicy = SortPolicy.BY_EXECUTE_TIME
|
policy: SortPolicy = SortPolicy.BY_EXECUTE_TIME,
|
||||||
|
order: Qt.SortOrder = Qt.SortOrder.AscendingOrder
|
||||||
):
|
):
|
||||||
|
|
||||||
if policy == SortPolicy.BY_NAME:
|
if policy == 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
|
||||||
)
|
)
|
||||||
elif policy == SortPolicy.BY_ADD_TIME:
|
elif policy == 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
|
||||||
)
|
)
|
||||||
elif policy == SortPolicy.BY_EXECUTE_TIME:
|
elif policy == 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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -315,6 +324,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
pending = 0
|
pending = 0
|
||||||
in_queue = 0
|
in_queue = 0
|
||||||
executed = 0
|
executed = 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"] == TimerTaskStatus.PENDING:
|
||||||
@@ -324,10 +334,14 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
in_queue += 1
|
in_queue += 1
|
||||||
elif timer_task["status"] == TimerTaskStatus.EXECUTED:
|
elif timer_task["status"] == TimerTaskStatus.EXECUTED:
|
||||||
executed += 1
|
executed += 1
|
||||||
|
elif timer_task["status"] == TimerTaskStatus.ERROR\
|
||||||
|
or timer_task["status"] == TimerTaskStatus.OUTDATED:
|
||||||
|
invalid += 1
|
||||||
self.TotalTaskLabel.setText(f"总任务:{total}")
|
self.TotalTaskLabel.setText(f"总任务:{total}")
|
||||||
self.PendingTaskLabel.setText(f"待执行:{pending}")
|
self.PendingTaskLabel.setText(f"待执行:{pending}")
|
||||||
self.InQueueTaskLabel.setText(f"队列中:{in_queue}")
|
self.InQueueTaskLabel.setText(f"队列中:{in_queue}")
|
||||||
self.ExecutedTaskLabel.setText(f"已执行:{executed}")
|
self.ExecutedTaskLabel.setText(f"已执行:{executed}")
|
||||||
|
self.InvalidTaskLabel.setText(f"无效的:{invalid}")
|
||||||
|
|
||||||
|
|
||||||
def updateTimerTaskList(
|
def updateTimerTaskList(
|
||||||
@@ -335,7 +349,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
):
|
):
|
||||||
|
|
||||||
self.TimerTasksListWidget.clear()
|
self.TimerTasksListWidget.clear()
|
||||||
self.sortTimerTasks(self.__sort_policy)
|
self.sortTimerTasks(self.__sort_policy, self.__sort_order)
|
||||||
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)
|
||||||
@@ -437,6 +451,18 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
self.__sort_policy = mapping[policy]
|
self.__sort_policy = mapping[policy]
|
||||||
self.updateTimerTaskList()
|
self.updateTimerTaskList()
|
||||||
|
|
||||||
|
@Slot()
|
||||||
|
def onSortOrderToggleButtonClicked(
|
||||||
|
self
|
||||||
|
):
|
||||||
|
|
||||||
|
self.__sort_order = Qt.SortOrder.AscendingOrder\
|
||||||
|
if self.__sort_order is Qt.SortOrder.DescendingOrder\
|
||||||
|
else Qt.SortOrder.DescendingOrder
|
||||||
|
self.TimerTaskSortOrderToggleButton.setText(
|
||||||
|
"↑" if self.__sort_order is Qt.SortOrder.AscendingOrder else "↓"
|
||||||
|
)
|
||||||
|
self.updateTimerTaskList()
|
||||||
|
|
||||||
@Slot()
|
@Slot()
|
||||||
def onTimerTasksChanged(
|
def onTimerTasksChanged(
|
||||||
@@ -470,3 +496,14 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
|||||||
if task["task_uuid"] == timer_task["task_uuid"]:
|
if task["task_uuid"] == timer_task["task_uuid"]:
|
||||||
task["status"] = TimerTaskStatus.EXECUTED
|
task["status"] = TimerTaskStatus.EXECUTED
|
||||||
self.timerTasksChanged.emit()
|
self.timerTasksChanged.emit()
|
||||||
|
|
||||||
|
@Slot(dict)
|
||||||
|
def onTimerTaskIsError(
|
||||||
|
self,
|
||||||
|
timer_task: dict
|
||||||
|
):
|
||||||
|
|
||||||
|
for task in self.__timer_tasks:
|
||||||
|
if task["task_uuid"] == timer_task["task_uuid"]:
|
||||||
|
task["status"] = TimerTaskStatus.ERROR
|
||||||
|
self.timerTasksChanged.emit()
|
||||||
|
|||||||
@@ -137,6 +137,30 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="InvalidTaskLabel">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>70</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>25</width>
|
||||||
|
<height>70</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QLabel {
|
||||||
|
color: #FF5722
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>无效的:0</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QFrame" name="TimerTaskSpaceFrame">
|
<widget class="QFrame" name="TimerTaskSpaceFrame">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
@@ -164,7 +188,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="TimerTaskSortLayout">
|
<layout class="QHBoxLayout" name="TimerTaskSortLayout">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>5</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QFrame" name="TimerTaskSortSpaceFrame">
|
<widget class="QFrame" name="TimerTaskSortSpaceFrame">
|
||||||
@@ -235,6 +259,25 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="TimerTaskSortOrderToggleButton">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>25</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>25</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>↑</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ class ALUserTreeWidget(QTreeWidget):
|
|||||||
self.setDefaultDropAction(Qt.DropAction.IgnoreAction)
|
self.setDefaultDropAction(Qt.DropAction.IgnoreAction)
|
||||||
self.setAlternatingRowColors(True)
|
self.setAlternatingRowColors(True)
|
||||||
self.setSortingEnabled(True)
|
self.setSortingEnabled(True)
|
||||||
|
self.sortByColumn(0, Qt.SortOrder.AscendingOrder)
|
||||||
self.setAnimated(True)
|
self.setAnimated(True)
|
||||||
self.setAllColumnsShowFocus(False)
|
self.setAllColumnsShowFocus(False)
|
||||||
self.setHeaderHidden(False)
|
self.setHeaderHidden(False)
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
AL_VERSION = "1.0.0-beta"
|
AL_VERSION = "1.0.0"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/res/icon">
|
<qresource prefix="/res/icon">
|
||||||
<file>icons/AutoLibrary.ico</file>
|
<file>icons/AutoLibrary_32x32.ico</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/res/trans">
|
<qresource prefix="/res/trans">
|
||||||
<file>translators/qtbase_zh_CN.qm</file>
|
<file>translators/qtbase_zh_CN.qm</file>
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
|
||||||
|
cd /d "%~dp0.."
|
||||||
|
|
||||||
|
echo [AutoLibrary complie] 检查翻译文件...
|
||||||
|
if exist translators (
|
||||||
|
cd translators
|
||||||
|
set ts_count=0
|
||||||
|
for %%f in (*.ts) do set /a ts_count+=1
|
||||||
|
|
||||||
|
if !ts_count! gtr 0 (
|
||||||
|
echo [AutoLibrary complie] 找到 !ts_count! 个 .ts 文件,开始编译翻译文件...
|
||||||
|
for %%f in (*.ts) do (
|
||||||
|
set "qm_filename=%%~nf.qm"
|
||||||
|
echo [AutoLibrary complie] 正在编译翻译文件: "%%f" -> "!qm_filename!"
|
||||||
|
|
||||||
|
pyside6-lrelease "%%f"
|
||||||
|
if !errorlevel! equ 0 (
|
||||||
|
echo [AutoLibrary complie] 翻译文件 "%%f" ✓ 编译成功,输出文件: "!qm_filename!"
|
||||||
|
) else (
|
||||||
|
echo [AutoLibrary complie] 翻译文件 "%%f" ✗ 编译失败
|
||||||
|
)
|
||||||
|
)
|
||||||
|
echo.
|
||||||
|
) else (
|
||||||
|
echo [AutoLibrary complie] 未找到任何 .ts 翻译文件
|
||||||
|
)
|
||||||
|
cd ..
|
||||||
|
) else (
|
||||||
|
echo [AutoLibrary complie] 未找到 translators 目录
|
||||||
|
)
|
||||||
|
echo.
|
||||||
|
|
||||||
|
set count=0
|
||||||
|
for %%f in (*.qrc) do set /a count+=1
|
||||||
|
|
||||||
|
if %count% equ 0 (
|
||||||
|
echo [AutoLibrary complie] 错误: 未找到任何 .qrc 文件
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo [AutoLibrary complie] 找到 %count% 个 .qrc 文件,开始编译...
|
||||||
|
echo.
|
||||||
|
|
||||||
|
for %%f in (*.qrc) do (
|
||||||
|
set "filename=%%~nf"
|
||||||
|
set "output_file=!filename!.py"
|
||||||
|
echo [AutoLibrary complie] 正在编译: "%%f" -> "!output_file!"
|
||||||
|
|
||||||
|
pyside6-rcc "%%f" -o "!output_file!"
|
||||||
|
if !errorlevel! equ 0 (
|
||||||
|
echo [AutoLibrary complie] 文件 "%%f" ✓ 编译成功,输出文件: "!output_file!"
|
||||||
|
) else (
|
||||||
|
echo [AutoLibrary complie] 文件 "%%f" ✗ 编译失败
|
||||||
|
)
|
||||||
|
echo.
|
||||||
|
)
|
||||||
|
|
||||||
|
echo [AutoLibrary complie] 所有操作完成。
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
PARENT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
cd "$PARENT_DIR"
|
||||||
|
|
||||||
|
echo "[AutoLibrary complie] 检查翻译文件..."
|
||||||
|
if [ -d "translators" ]; then
|
||||||
|
cd translators
|
||||||
|
ts_files=(*.ts)
|
||||||
|
ts_count=${#ts_files[@]}
|
||||||
|
|
||||||
|
# 如果第一个元素是"*.ts"(表示没有匹配),则数量为0
|
||||||
|
if [ "$ts_count" -eq 1 ] && [ "${ts_files[0]}" = "*.ts" ]; then
|
||||||
|
ts_count=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $ts_count -gt 0 ]; then
|
||||||
|
echo "[AutoLibrary complie] 找到 $ts_count 个 .ts 文件,开始编译翻译文件..."
|
||||||
|
for file in *.ts; do
|
||||||
|
base_name=$(basename "$file" .ts)
|
||||||
|
qm_file="${base_name}.qm"
|
||||||
|
echo "[AutoLibrary complie] 正在编译翻译文件: \"$file\" -> \"$qm_file\""
|
||||||
|
|
||||||
|
if pyside6-lrelease "$file"; then
|
||||||
|
echo "[AutoLibrary complie] 翻译文件 \"$file\" ✓ 编译成功,输出文件: \"$qm_file\""
|
||||||
|
else
|
||||||
|
echo "[AutoLibrary complie] 翻译文件 \"$file\" ✗ 编译失败"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
else
|
||||||
|
echo "[AutoLibrary complie] 未找到任何 .ts 翻译文件"
|
||||||
|
fi
|
||||||
|
cd ..
|
||||||
|
else
|
||||||
|
echo "[AutoLibrary complie] 未找到 translators 目录"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
|
||||||
|
file_count=$(ls *.qrc 2>/dev/null | wc -l)
|
||||||
|
|
||||||
|
if [ $file_count -eq 0 ]; then
|
||||||
|
echo "[AutoLibrary complie] 错误: 未找到任何 .qrc 文件"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[AutoLibrary complie] 找到 $file_count 个 .qrc 文件,开始编译..."
|
||||||
|
echo
|
||||||
|
|
||||||
|
for file in *.qrc; do
|
||||||
|
base_name=$(basename "$file" .qrc)
|
||||||
|
output_file="${base_name}.py"
|
||||||
|
echo "[AutoLibrary complie] 正在编译: \"$file\" -> \"$output_file\""
|
||||||
|
|
||||||
|
if pyside6-rcc "$file" -o "$output_file"; then
|
||||||
|
echo "[AutoLibrary complie] 文件 \"$file\" ✓ 编译成功,输出文件: \"$output_file\""
|
||||||
|
else
|
||||||
|
echo "[AutoLibrary complie] 文件 \"$file\" ✗ 编译失败"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "[AutoLibrary complie] 所有操作完成。"
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
|
||||||
|
cd /d "%~dp0.."
|
||||||
|
|
||||||
|
set count=0
|
||||||
|
for %%f in (*.ui) do set /a count+=1
|
||||||
|
|
||||||
|
if %count% equ 0 (
|
||||||
|
echo [AutoLibrary complie] 错误: 未找到任何 .ui 文件
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo [AutoLibrary complie] 找到 %count% 个 .ui 文件,开始编译...
|
||||||
|
echo.
|
||||||
|
|
||||||
|
for %%f in (*.ui) do (
|
||||||
|
set "filename=%%~nf"
|
||||||
|
set "output_file=Ui_!filename!.py"
|
||||||
|
echo [AutoLibrary complie] 正在编译: "%%f" -> "!output_file!"
|
||||||
|
|
||||||
|
pyside6-uic "%%f" -o "!output_file!"
|
||||||
|
if !errorlevel! equ 0 (
|
||||||
|
echo [AutoLibrary complie] 文件 "%%f" ✓ 编译成功,输出文件: "!output_file!"
|
||||||
|
) else (
|
||||||
|
echo [AutoLibrary complie] 文件 "%%f" ✗ 编译失败
|
||||||
|
)
|
||||||
|
echo.
|
||||||
|
)
|
||||||
|
|
||||||
|
echo [AutoLibrary complie] 所有操作完成。
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
PARENT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
cd "$PARENT_DIR"
|
||||||
|
|
||||||
|
file_count=$(ls *.ui 2>/dev/null | wc -l)
|
||||||
|
|
||||||
|
if [ $file_count -eq 0 ]; then
|
||||||
|
echo "[AutoLibrary complie] 错误: 未找到任何 .ui 文件"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[AutoLibrary complie] 找到 $file_count 个 .ui 文件,开始编译..."
|
||||||
|
echo
|
||||||
|
|
||||||
|
for file in *.ui; do
|
||||||
|
base_name=$(basename "$file" .ui)
|
||||||
|
output_file="Ui_${base_name}.py"
|
||||||
|
echo "[AutoLibrary complie] 正在编译: \"$file\" -> \"$output_file\""
|
||||||
|
|
||||||
|
if pyside6-uic "$file" -o "$output_file"; then
|
||||||
|
echo "[AutoLibrary complie] 文件 \"$file\" ✓ 编译成功,输出文件: \"$output_file\""
|
||||||
|
else
|
||||||
|
echo "[AutoLibrary complie] 文件 \"$file\" ✗ 编译失败"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "[AutoLibrary complie] 所有操作完成。"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
this folder is used to store the batch scripts.
|
||||||
|
Before Width: | Height: | Size: 785 KiB After Width: | Height: | Size: 785 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
@@ -41,10 +41,10 @@ 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():
|
||||||
return None
|
raise Exception("浏览器驱动初始化失败")
|
||||||
else:
|
else:
|
||||||
if not self.__initDriverUrl():
|
if not self.__initDriverUrl():
|
||||||
return None
|
raise Exception("浏览器驱动URL初始化失败")
|
||||||
self.__initLibOperators()
|
self.__initLibOperators()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user