mirror of
https://github.com/KenanZhu/AutoLibrary.git
synced 2026-08-01 21:59:36 +08:00
327 lines
12 KiB
Python
327 lines
12 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
Copyright (c) 2025 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.
|
|
"""
|
|
import uuid
|
|
|
|
from enum import Enum
|
|
from datetime import datetime, timedelta
|
|
|
|
from PySide6.QtCore import (
|
|
Slot,
|
|
QDateTime,
|
|
QUrl
|
|
)
|
|
from PySide6.QtGui import QDesktopServices
|
|
from PySide6.QtWidgets import (
|
|
QLabel,
|
|
QDialog,
|
|
QWidget,
|
|
QSpinBox,
|
|
QHBoxLayout,
|
|
QVBoxLayout,
|
|
QDateTimeEdit,
|
|
QGroupBox,
|
|
QPushButton
|
|
)
|
|
|
|
from gui.resources.ui.Ui_ALTimerTaskAddDialog import Ui_ALTimerTaskAddDialog
|
|
from utils.TimerUtils import TimerUtils
|
|
|
|
|
|
class ALTimerTaskStatus(Enum):
|
|
|
|
PENDING = "等待中"
|
|
READY = "已就绪"
|
|
RUNNING = "执行中"
|
|
EXECUTED = "已执行"
|
|
ERROR = "执行失败"
|
|
OUTDATED = "已过期"
|
|
UNKNOWN = "未知"
|
|
|
|
|
|
class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
|
|
|
|
def __init__(
|
|
self,
|
|
parent = None,
|
|
timer_task: dict = None
|
|
):
|
|
|
|
super().__init__(parent)
|
|
self.__edit_timer_task = timer_task
|
|
|
|
self.setupUi(self)
|
|
self.modifyUi()
|
|
self.connectSignals()
|
|
|
|
if self.__edit_timer_task:
|
|
self.loadTask(self.__edit_timer_task)
|
|
|
|
def modifyUi(
|
|
self
|
|
):
|
|
|
|
self.TimerTypeComboBox.setCurrentIndex(0)
|
|
self.SpecificTimerWidget = QWidget()
|
|
self.SpecificTimerLayout = QHBoxLayout(self.SpecificTimerWidget)
|
|
self.SpecificTimerLayout.setContentsMargins(0, 0, 0, 0)
|
|
self.SpecificTimerLayout.setSpacing(5)
|
|
self.SpecificTimerLayout.addWidget(QLabel("定时时间:"))
|
|
self.SpecificDateTimeEdit = QDateTimeEdit()
|
|
self.SpecificDateTimeEdit.setCalendarPopup(True)
|
|
self.SpecificDateTimeEdit.setDisplayFormat("yyyy-MM-dd HH:mm:ss")
|
|
self.SpecificDateTimeEdit.setMinimumDateTime(QDateTime.currentDateTime())
|
|
self.SpecificDateTimeEdit.setDateTime(QDateTime.currentDateTime().addSecs(60))
|
|
self.SpecificTimerLayout.addWidget(self.SpecificDateTimeEdit)
|
|
self.TimerConfigLayout.addWidget(self.SpecificTimerWidget)
|
|
self.RelativeTimerWidget = QWidget()
|
|
self.RelativeTimerLayout = QHBoxLayout(self.RelativeTimerWidget)
|
|
self.RelativeTimerLayout.setContentsMargins(0, 0, 0, 0)
|
|
self.RelativeTimerLayout.setSpacing(5)
|
|
self.RelativeTimerLayout.addWidget(QLabel("相对时间:"))
|
|
self.RelativeDaySpinBox = QSpinBox()
|
|
self.RelativeDaySpinBox.setMinimum(0)
|
|
self.RelativeDaySpinBox.setMaximum(364)
|
|
self.RelativeDaySpinBox.setSuffix("天")
|
|
self.RelativeTimerLayout.addWidget(self.RelativeDaySpinBox)
|
|
self.RelativeHourSpinBox = QSpinBox()
|
|
self.RelativeHourSpinBox.setMinimum(0)
|
|
self.RelativeHourSpinBox.setMaximum(23)
|
|
self.RelativeHourSpinBox.setSuffix("时")
|
|
self.RelativeTimerLayout.addWidget(self.RelativeHourSpinBox)
|
|
self.RelativeMinuteSpinBox = QSpinBox()
|
|
self.RelativeMinuteSpinBox.setMinimum(0)
|
|
self.RelativeMinuteSpinBox.setMaximum(59)
|
|
self.RelativeMinuteSpinBox.setSuffix("分")
|
|
self.RelativeTimerLayout.addWidget(self.RelativeMinuteSpinBox)
|
|
self.RelativeSecondSpinBox = QSpinBox()
|
|
self.RelativeSecondSpinBox.setMinimum(0)
|
|
self.RelativeSecondSpinBox.setMaximum(59)
|
|
self.RelativeSecondSpinBox.setSuffix("秒")
|
|
self.RelativeTimerLayout.addWidget(self.RelativeSecondSpinBox)
|
|
self.TimerConfigLayout.addWidget(self.RelativeTimerWidget)
|
|
self.RelativeTimerWidget.setVisible(False)
|
|
self.AutoScriptGroupBox = QGroupBox("AutoScript 指令")
|
|
self.AutoScriptLayout = QVBoxLayout(self.AutoScriptGroupBox)
|
|
self.AutoScriptLayout.setContentsMargins(3, 3, 3, 3)
|
|
self.AutoScriptLayout.setSpacing(3)
|
|
AutoScriptBtnLayout = QHBoxLayout()
|
|
self.AutoScriptEditButton = QPushButton("编辑")
|
|
self.AutoScriptEditButton.setMinimumHeight(25)
|
|
self.AutoScriptEditButton.setFixedWidth(80)
|
|
AutoScriptBtnLayout.addWidget(self.AutoScriptEditButton)
|
|
AutoScriptBtnLayout.addStretch()
|
|
self.AutoScriptHelpButton = QPushButton("?")
|
|
self.AutoScriptHelpButton.setFixedSize(20, 20)
|
|
self.AutoScriptHelpButton.setToolTip(
|
|
"AutoScript 是一种轻量级 DSL 语言,基于 Lua 实现。\n"
|
|
"用于在重复定时任务执行前,对用户的预约数据进行预处理\n"
|
|
"\n"
|
|
"点击查看完整在线文档"
|
|
)
|
|
self.AutoScriptHelpButton.setStyleSheet(
|
|
"QPushButton { border-radius: 10px; border: 1px solid #999; "
|
|
"font-weight: bold; color: #555; }"
|
|
"QPushButton:hover { background-color: #E0E0E0; }"
|
|
)
|
|
AutoScriptBtnLayout.addWidget(self.AutoScriptHelpButton)
|
|
self.AutoScriptStatusLabel = QLabel("未设置")
|
|
self.AutoScriptStatusLabel.setStyleSheet("color: #969696;")
|
|
self.AutoScriptStatusLabel.setFixedHeight(25)
|
|
AutoScriptBtnLayout.addWidget(self.AutoScriptStatusLabel)
|
|
self.AutoScriptLayout.addLayout(AutoScriptBtnLayout)
|
|
self.ALAddTimerTaskLayout.insertWidget(
|
|
self.ALAddTimerTaskLayout.indexOf(self.TaskConfigGroupBox) + 1,
|
|
self.AutoScriptGroupBox
|
|
)
|
|
self.AutoScriptGroupBox.setVisible(False)
|
|
self.__auto_script = ""
|
|
self.__mock_target_data = None
|
|
|
|
def loadTask(
|
|
self,
|
|
task: dict
|
|
):
|
|
|
|
self.TaskNameLineEdit.setText(task.get("name", ""))
|
|
time_type = task.get("time_type", "特定时间")
|
|
self.TimerTypeComboBox.setCurrentText(time_type)
|
|
self.SpecificDateTimeEdit.setDateTime(
|
|
QDateTime(task["execute_time"])
|
|
)
|
|
self.RelativeDaySpinBox.setValue(0)
|
|
self.RelativeHourSpinBox.setValue(0)
|
|
self.RelativeMinuteSpinBox.setValue(0)
|
|
self.RelativeSecondSpinBox.setValue(0)
|
|
if task.get("silent", False):
|
|
self.SilentlyRunRadioButton.setChecked(True)
|
|
else:
|
|
self.ShowBeforeRunRadioButton.setChecked(True)
|
|
repeat = task.get("repeat", False)
|
|
self.RepeatCheckBox.setChecked(repeat)
|
|
if repeat:
|
|
repeat_days = task.get("repeat_days", [])
|
|
self.MonCheckBox.setChecked(0 in repeat_days)
|
|
self.TueCheckBox.setChecked(1 in repeat_days)
|
|
self.WedCheckBox.setChecked(2 in repeat_days)
|
|
self.ThuCheckBox.setChecked(3 in repeat_days)
|
|
self.FriCheckBox.setChecked(4 in repeat_days)
|
|
self.SatCheckBox.setChecked(5 in repeat_days)
|
|
self.SunCheckBox.setChecked(6 in repeat_days)
|
|
auto_script = task.get("repeat_auto_script", "")
|
|
if auto_script:
|
|
self.__auto_script = auto_script
|
|
self.AutoScriptStatusLabel.setText("已设置")
|
|
self.AutoScriptStatusLabel.setStyleSheet("color: #4CAF50;")
|
|
mock_data = task.get("mock_target_data")
|
|
if mock_data:
|
|
self.__mock_target_data = mock_data
|
|
self.ConfirmButton.setText("保存")
|
|
|
|
def connectSignals(
|
|
self
|
|
):
|
|
|
|
self.CancelButton.clicked.connect(self.reject)
|
|
self.ConfirmButton.clicked.connect(self.accept)
|
|
self.TimerTypeComboBox.currentIndexChanged.connect(self.onTimerTypeComboBoxIndexChanged)
|
|
self.RepeatCheckBox.toggled.connect(self.onRepeatCheckBoxToggled)
|
|
self.AutoScriptEditButton.clicked.connect(self.onPreviewAutoScript)
|
|
self.AutoScriptHelpButton.clicked.connect(self.onAutoScriptHelp)
|
|
|
|
def getTimerTask(
|
|
self
|
|
) -> dict:
|
|
|
|
added_time = datetime.now()
|
|
if not self.TaskNameLineEdit.text():
|
|
name = f"未命名任务-{added_time.strftime("%Y%m%d%H%M%S")}"
|
|
else:
|
|
name = self.TaskNameLineEdit.text()
|
|
timer_type_index = self.TimerTypeComboBox.currentIndex()
|
|
silent = not self.ShowBeforeRunRadioButton.isChecked()
|
|
if timer_type_index == 0:
|
|
execute_time = self.SpecificDateTimeEdit.dateTime()
|
|
tmp_time_str = execute_time.toString("yyyy-MM-dd HH:mm:ss")
|
|
execute_time = datetime.strptime(tmp_time_str, "%Y-%m-%d %H:%M:%S")
|
|
else:
|
|
execute_time = datetime.now() + timedelta(
|
|
days = self.RelativeDaySpinBox.value(),
|
|
hours = self.RelativeHourSpinBox.value(),
|
|
minutes = self.RelativeMinuteSpinBox.value(),
|
|
seconds = self.RelativeSecondSpinBox.value()
|
|
)
|
|
|
|
if self.__edit_timer_task:
|
|
task_data = dict(self.__edit_timer_task)
|
|
task_data["name"] = name
|
|
task_data["execute_time"] = execute_time
|
|
task_data["silent"] = silent
|
|
task_data["status"] = ALTimerTaskStatus.PENDING
|
|
task_data["executed"] = False
|
|
task_data["repeat_auto_script"] = self.__auto_script
|
|
task_data["mock_target_data"] = self.__mock_target_data
|
|
else:
|
|
task_data = {
|
|
"name": name,
|
|
"uuid": uuid.uuid4().hex.upper() + f"-{added_time.strftime("%Y%m%d%H%M%S")}",
|
|
"time_type": self.TimerTypeComboBox.currentText(),
|
|
"execute_time": execute_time,
|
|
"silent": silent,
|
|
"added_time": added_time,
|
|
"status": ALTimerTaskStatus.PENDING,
|
|
"executed": False,
|
|
"repeat": self.RepeatCheckBox.isChecked(),
|
|
"repeat_auto_script": self.__auto_script,
|
|
"mock_target_data": self.__mock_target_data,
|
|
}
|
|
|
|
repeat = self.RepeatCheckBox.isChecked()
|
|
task_data["repeat"] = repeat
|
|
if repeat:
|
|
if "repeat_history" not in task_data:
|
|
task_data["repeat_history"] = []
|
|
repeat_days = []
|
|
if self.MonCheckBox.isChecked():
|
|
repeat_days.append(0)
|
|
if self.TueCheckBox.isChecked():
|
|
repeat_days.append(1)
|
|
if self.WedCheckBox.isChecked():
|
|
repeat_days.append(2)
|
|
if self.ThuCheckBox.isChecked():
|
|
repeat_days.append(3)
|
|
if self.FriCheckBox.isChecked():
|
|
repeat_days.append(4)
|
|
if self.SatCheckBox.isChecked():
|
|
repeat_days.append(5)
|
|
if self.SunCheckBox.isChecked():
|
|
repeat_days.append(6)
|
|
if not repeat_days:
|
|
repeat_days = [0, 1, 2, 3, 4, 5, 6]
|
|
task_data["repeat_days"] = repeat_days
|
|
task_data["repeat_hour"] = execute_time.hour
|
|
task_data["repeat_minute"] = execute_time.minute
|
|
task_data["repeat_second"] = execute_time.second
|
|
task_data["execute_time"] = TimerUtils.getNextTimerRepeatTime(
|
|
task_data["repeat_days"],
|
|
task_data["repeat_hour"],
|
|
task_data["repeat_minute"],
|
|
task_data["repeat_second"]
|
|
)
|
|
return task_data
|
|
|
|
@Slot(int)
|
|
def onTimerTypeComboBoxIndexChanged(
|
|
self,
|
|
index: int
|
|
):
|
|
|
|
self.SpecificTimerWidget.setVisible(index == 0)
|
|
self.RelativeTimerWidget.setVisible(index == 1)
|
|
|
|
@Slot(bool)
|
|
def onRepeatCheckBoxToggled(
|
|
self,
|
|
checked: bool
|
|
):
|
|
|
|
self.MonCheckBox.setEnabled(checked)
|
|
self.TueCheckBox.setEnabled(checked)
|
|
self.WedCheckBox.setEnabled(checked)
|
|
self.ThuCheckBox.setEnabled(checked)
|
|
self.FriCheckBox.setEnabled(checked)
|
|
self.SatCheckBox.setEnabled(checked)
|
|
self.SunCheckBox.setEnabled(checked)
|
|
self.AutoScriptGroupBox.setVisible(checked)
|
|
|
|
@Slot()
|
|
def onPreviewAutoScript(self):
|
|
from gui.ALAutoScriptEditDialog import ALAutoScriptEditDialog
|
|
Dlg = ALAutoScriptEditDialog(self, self.__auto_script, self.__mock_target_data)
|
|
if Dlg.exec() == QDialog.DialogCode.Accepted:
|
|
script = Dlg.getScript()
|
|
self.__auto_script = script
|
|
self.__mock_target_data = Dlg.getMockData()
|
|
if script:
|
|
self.AutoScriptStatusLabel.setText("已设置")
|
|
self.AutoScriptStatusLabel.setStyleSheet("color: #4CAF50;")
|
|
else:
|
|
self.AutoScriptStatusLabel.setText("未设置")
|
|
self.AutoScriptStatusLabel.setStyleSheet("color: #969696;")
|
|
Dlg.deleteLater()
|
|
|
|
@Slot()
|
|
def onAutoScriptHelp(
|
|
self
|
|
):
|
|
|
|
QDesktopServices.openUrl(
|
|
QUrl("https://manuals.autolibrary.kenanzhu.com/zh/autoscript")
|
|
)
|