1
1
mirror of https://github.com/KenanZhu/AutoLibrary.git synced 2026-06-18 07:23:03 +08:00

feat(autoscript): 将预处理脚本重构为 AutoScript DSL,新增可视化编排与预览对话框

This commit is contained in:
2026-05-08 20:46:54 +08:00
parent 4d0d7a952c
commit 46b3447d1e
7 changed files with 258 additions and 174 deletions
@@ -17,10 +17,10 @@ from PySide6.QtWidgets import (
QGroupBox, QSizePolicy
)
from utils.PreprocEngine import PreprocEngine
from utils.AutoScriptEngine import AutoScriptEngine
VARIABLE_META = PreprocEngine.VARIABLE_META
VARIABLE_META = AutoScriptEngine.VARIABLE_META
_VAR_COMBO_ITEMS = [
(display, varname, vartype)
@@ -637,7 +637,7 @@ class ConditionalBlock(QGroupBox):
return len(self._actionWidgets)
class ALPreprocOrchDialog(QDialog):
class ALAutoScriptOrchDialog(QDialog):
def __init__(
self,
@@ -661,7 +661,7 @@ class ALPreprocOrchDialog(QDialog):
self
):
self.setWindowTitle("预处理指令编排 - AutoLibrary")
self.setWindowTitle("AutoScript 指令编排 - AutoLibrary")
self.setMinimumSize(420, 400)
self.setModal(True)
mainLayout = QVBoxLayout(self)
@@ -31,41 +31,41 @@ class ALScriptHighlighter(QSyntaxHighlighter):
keywordFmt.setForeground(QColor("#316BFF"))
keywordFmt.setFontWeight(QFont.Weight.Bold)
for kw in ["IF", "ELSE IF", "ELSE", "ENDIF", "END IF",
"SET", "PASS", "THEN", ".TRUE.", ".FALSE."]:
"SET", "PASS", "THEN"]:
pattern = r"\b" + kw.replace(" ", r"\s+") + r"\b"
self._rules.append((pattern, keywordFmt))
literalFmt = QTextCharFormat()
literalFmt.setForeground(QColor("#C2185B"))
literalFmt.setFontWeight(QFont.Weight.Bold)
for lit in [".TRUE.", ".FALSE."]:
self._rules.append((r"\b" + lit.replace(".", r"\.") + r"\b", literalFmt))
opFmt = QTextCharFormat()
opFmt.setForeground(QColor("#9C27B0"))
for op in [r"\.EQ\.", r"\.NEQ\.", r"\.BGT\.", r"\.BLT\.",
r"\.BGE\.", r"\.BLE\.", r"\.ADD\.", r"\.SUB\."]:
self._rules.append((op, opFmt))
varFmt = QTextCharFormat()
varFmt.setForeground(QColor("#E65100"))
for var in ["RESERVE_BEGIN_TIME", "RESERVE_END_TIME",
"RESERVE_DATE", "USERNAME", "USER_ENABLE",
"PRIORITY", "CURRENT_TIME", "CURRENT_DATE"]:
self._rules.append((r"\b" + var + r"\b", varFmt))
funcFmt = QTextCharFormat()
funcFmt.setForeground(QColor("#2E7D32"))
self._rules.append((r"\bTIME\([^)]+\)", funcFmt))
self._rules.append((r"\bDATE\([^)]+\)", funcFmt))
strFmt = QTextCharFormat()
strFmt.setForeground(QColor("#388E3C"))
self._rules.append((r"'[^']*'", strFmt))
numFmt = QTextCharFormat()
numFmt.setForeground(QColor("#D32F2F"))
self._rules.append((r"\b\d+\b", numFmt))
commentFmt = QTextCharFormat()
commentFmt.setForeground(QColor("#999999"))
commentFmt.setFontItalic(True)
self._rules.append((r"//[^\n]*", commentFmt))
def highlightBlock(
self,
text
@@ -79,7 +79,7 @@ class ALScriptHighlighter(QSyntaxHighlighter):
self.setFormat(start, length, fmt)
class ALScriptPreviewDialog(QDialog):
class ALAutoScriptPreviewDialog(QDialog):
def __init__(
self,
@@ -88,7 +88,6 @@ class ALScriptPreviewDialog(QDialog):
):
super().__init__(parent)
self.__fontSize = 13
self.modifyUi()
@@ -104,7 +103,7 @@ class ALScriptPreviewDialog(QDialog):
self
):
self.setWindowTitle("预处理脚本预览 - AutoLibrary")
self.setWindowTitle("AutoScript 预览 - AutoLibrary")
self.setMinimumSize(520, 360)
layout = QVBoxLayout(self)
@@ -136,7 +135,6 @@ class ALScriptPreviewDialog(QDialog):
self._copyBtn.setToolTip("复制脚本")
toolbarLayout.addWidget(self._copyBtn)
layout.addLayout(toolbarLayout)
self._textEdit = QPlainTextEdit(self)
self._textEdit.setReadOnly(True)
self._textEdit.setLineWrapMode(
+10 -9
View File
@@ -18,7 +18,7 @@ from PySide6.QtCore import (
from base.MsgBase import MsgBase
from operators.AutoLib import AutoLib
from utils.JSONReader import JSONReader
from utils.PreprocEngine import PreprocEngine
from utils.AutoScriptEngine import AutoScriptEngine
class AutoLibWorker(MsgBase, QThread):
@@ -161,6 +161,7 @@ class TimerTaskWorker(AutoLibWorker):
self.autoLibWorkerIsFinished.connect(self.onTimerTaskIsFinished)
self.autoLibWorkerFinishedWithError.connect(self.onTimerTaskFinishedWithError)
def run(
self
):
@@ -173,7 +174,7 @@ class TimerTaskWorker(AutoLibWorker):
try:
if not self.loadConfigs():
raise Exception("配置文件加载失败")
self._applyRepeatPreproc()
self._applyRepeatAutoScript()
auto_lib = AutoLib(
self._input_queue,
self._output_queue,
@@ -206,15 +207,15 @@ class TimerTaskWorker(AutoLibWorker):
self.timerTaskWorkerIsFinished.emit(False, self.__timer_task)
def _applyRepeatPreproc(
def _applyRepeatAutoScript(
self
):
preproc_script = self.__timer_task.get("repeat_preproc", "")
if not preproc_script or not preproc_script.strip():
auto_script = self.__timer_task.get("repeat_auto_script", "")
if not auto_script or not auto_script.strip():
return
self._showTrace(
f"检测到重复定时任务预处理脚本, 开始执行...",
f"检测到重复定时任务 AutoScript, 开始执行...",
no_log=True
)
groups = self._user_config.get("groups", [])
@@ -224,15 +225,15 @@ class TimerTaskWorker(AutoLibWorker):
continue
for user in group.get("users", []):
try:
PreprocEngine.execute(preproc_script, user)
AutoScriptEngine.execute(auto_script, user)
affected_count += 1
except ValueError as e:
self._showTrace(
f"预处理脚本执行错误 (用户 {user['username']}): {e}",
f"AutoScript 执行错误 (用户 {user['username']}): {e}",
self.TraceLevel.ERROR
)
self._showLog(
f"预处理脚本执行完毕, "
f"AutoScript 执行完毕, "
f"影响 {affected_count} 个用户",
self.TraceLevel.INFO
)
+71 -46
View File
@@ -12,11 +12,12 @@ import uuid
from enum import Enum
from datetime import datetime, timedelta
from PySide6.QtCore import Slot, QDateTime
from PySide6.QtCore import Slot, QDateTime, QUrl
from PySide6.QtGui import QDesktopServices
from PySide6.QtWidgets import QLabel, QDialog, QWidget, QSpinBox, QHBoxLayout, QVBoxLayout, QGridLayout, QDateTimeEdit, QGroupBox, QPushButton
from gui.resources.ui.Ui_ALTimerTaskAddDialog import Ui_ALTimerTaskAddDialog
from gui.ALPreprocOrchDialog import ALPreprocOrchDialog
from gui.ALAutoScriptOrchDialog import ALAutoScriptOrchDialog
from utils.TimerUtils import TimerUtils
@@ -87,32 +88,46 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
self.TimerConfigLayout.addWidget(self.RelativeTimerWidget)
self.RelativeTimerWidget.setVisible(False)
self.PreprocGroupBox = QGroupBox("预处理脚本")
self.PreprocLayout = QVBoxLayout(self.PreprocGroupBox)
self.PreprocLayout.setContentsMargins(3, 3, 3, 3)
self.PreprocLayout.setSpacing(3)
preproc_btn_layout = QHBoxLayout()
self.PreprocSetButton = QPushButton("设置预处理指令")
self.PreprocSetButton.setMinimumHeight(25)
self.PreprocSetButton.setFixedWidth(130)
preproc_btn_layout.addWidget(self.PreprocSetButton)
self.PreprocPreviewButton = QPushButton("预览")
self.PreprocPreviewButton.setMinimumHeight(25)
self.PreprocPreviewButton.setFixedWidth(60)
self.PreprocPreviewButton.setEnabled(False)
preproc_btn_layout.addWidget(self.PreprocPreviewButton)
preproc_btn_layout.addStretch()
self.PreprocStatusLabel = QLabel("未设置")
self.PreprocStatusLabel.setStyleSheet("color: #969696;")
self.PreprocStatusLabel.setFixedHeight(25)
preproc_btn_layout.addWidget(self.PreprocStatusLabel)
self.PreprocLayout.addLayout(preproc_btn_layout)
self.AutoScriptGroupBox = QGroupBox("AutoScript 指令")
self.AutoScriptLayout = QVBoxLayout(self.AutoScriptGroupBox)
self.AutoScriptLayout.setContentsMargins(3, 3, 3, 3)
self.AutoScriptLayout.setSpacing(3)
autoScriptBtnLayout = QHBoxLayout()
self.AutoScriptSetButton = QPushButton("设置指令")
self.AutoScriptSetButton.setMinimumHeight(25)
self.AutoScriptSetButton.setFixedWidth(130)
autoScriptBtnLayout.addWidget(self.AutoScriptSetButton)
self.AutoScriptPreviewButton = QPushButton("预览")
self.AutoScriptPreviewButton.setMinimumHeight(25)
self.AutoScriptPreviewButton.setFixedWidth(60)
self.AutoScriptPreviewButton.setEnabled(False)
autoScriptBtnLayout.addWidget(self.AutoScriptPreviewButton)
autoScriptBtnLayout.addStretch()
self.AutoScriptHelpButton = QPushButton("?")
self.AutoScriptHelpButton.setFixedSize(20, 20)
self.AutoScriptHelpButton.setToolTip(
"AutoScript 是一种轻量级 DSL\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.PreprocGroupBox
self.AutoScriptGroupBox
)
self.__repeat_preproc_script = ""
self.AutoScriptGroupBox.setVisible(False)
self.__auto_script = ""
def connectSignals(
@@ -123,35 +138,44 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
self.ConfirmButton.clicked.connect(self.accept)
self.TimerTypeComboBox.currentIndexChanged.connect(self.onTimerTypeComboBoxIndexChanged)
self.RepeatCheckBox.toggled.connect(self.onRepeatCheckBoxToggled)
self.PreprocSetButton.clicked.connect(self._onSetPreproc)
self.PreprocPreviewButton.clicked.connect(self._onPreviewPreproc)
self.AutoScriptSetButton.clicked.connect(self._onSetAutoScript)
self.AutoScriptPreviewButton.clicked.connect(self._onPreviewAutoScript)
self.AutoScriptHelpButton.clicked.connect(self._onAutoScriptHelp)
@Slot()
def _onSetPreproc(self):
dlg = ALPreprocOrchDialog(self, existingScript=self.__repeat_preproc_script)
def _onSetAutoScript(self):
dlg = ALAutoScriptOrchDialog(self, existingScript=self.__auto_script)
if dlg.exec() == QDialog.DialogCode.Accepted:
script = dlg.getScript()
self.__repeat_preproc_script = script
self.__auto_script = script
if script:
self.PreprocStatusLabel.setText("已设置")
self.PreprocStatusLabel.setStyleSheet("color: #4CAF50;")
self.PreprocPreviewButton.setEnabled(True)
self.AutoScriptStatusLabel.setText("已设置")
self.AutoScriptStatusLabel.setStyleSheet("color: #4CAF50;")
self.AutoScriptPreviewButton.setEnabled(True)
else:
self.PreprocStatusLabel.setText("未设置")
self.PreprocStatusLabel.setStyleSheet("color: #969696;")
self.PreprocPreviewButton.setEnabled(False)
self.AutoScriptStatusLabel.setText("未设置")
self.AutoScriptStatusLabel.setStyleSheet("color: #969696;")
self.AutoScriptPreviewButton.setEnabled(False)
dlg.deleteLater()
@Slot()
def _onPreviewAutoScript(self):
if not self.__auto_script:
return
from gui.ALAutoScriptPrevDialog import ALAutoScriptPreviewDialog
dlg = ALAutoScriptPreviewDialog(self, self.__auto_script)
dlg.exec()
dlg.deleteLater()
@Slot()
def _onPreviewPreproc(self):
if not self.__repeat_preproc_script:
return
from gui.ALPreProcPrevDialog import ALScriptPreviewDialog
dlg = ALScriptPreviewDialog(self, self.__repeat_preproc_script)
dlg.exec()
dlg.deleteLater()
def _onAutoScriptHelp(
self
):
QDesktopServices.openUrl(
QUrl("https://www.autolibrary.kenanzhu.com/manuals/autoscript")
)
def getTimerTask(
@@ -186,7 +210,7 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
"status": ALTimerTaskStatus.PENDING,
"executed": False,
"repeat": self.RepeatCheckBox.isChecked(),
"repeat_preproc": self.__repeat_preproc_script,
"repeat_auto_script": self.__auto_script,
}
if task_data["repeat"]:
task_data["history"] = [] # repeat history
@@ -240,4 +264,5 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
self.ThuCheckBox.setEnabled(checked)
self.FriCheckBox.setEnabled(checked)
self.SatCheckBox.setEnabled(checked)
self.SunCheckBox.setEnabled(checked)
self.SunCheckBox.setEnabled(checked)
self.AutoScriptGroupBox.setVisible(checked)
+1 -1
View File
@@ -10,7 +10,7 @@
- ALSeatMapTable: Seat map table class.
- ALSeatMapSelectDialog: Seat map select dialog class.
- ALTimerTaskAddDialog: Timer task add dialog class.
- ALPreprocOrchDialog: Preprocessing script orchestration dialog class.
- ALAutoScriptOrchDialog: AutoScript orchestration dialog class.
- ALTimerTaskHistoryDialog: Timer task history dialog class.
- ALTimerTaskManageWidget: Timer task manage widget class.
- ALUserTreeWidget: User tree widget class.