From 7f5478b0986b80ddb331a11d1f2f7791fb610a3d Mon Sep 17 00:00:00 2001 From: DLmaster Date: Thu, 6 Feb 2025 23:33:00 +0800 Subject: [PATCH] =?UTF-8?q?feat(core):=20=E6=B7=BB=E5=8A=A0=E8=B0=83?= =?UTF-8?q?=E5=BA=A6=E9=98=9F=E5=88=97=E5=AE=8C=E6=88=90=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E5=90=8E=E8=A1=8C=E4=B8=BA=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/core/config.py | 9 ++++-- app/core/main_info_bar.py | 14 ++++----- app/core/task_manager.py | 15 +++++++-- app/models/MAA.py | 7 ----- app/services/system.py | 66 +++++++++++++++++++++++++++++++++++++-- app/ui/dispatch_center.py | 2 +- app/ui/main_window.py | 10 ++---- app/ui/member_manager.py | 30 +++++------------- app/ui/queue_manager.py | 17 +++++++++- app/ui/setting.py | 31 ++++++------------ resources/version.json | 4 +-- 11 files changed, 127 insertions(+), 78 deletions(-) diff --git a/app/core/config.py b/app/core/config.py index b9d1a1d..6f05a49 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -499,6 +499,7 @@ class AppConfig: self.queue_config.set(self.queue_config.queueSet_Name, "") self.queue_config.set(self.queue_config.queueSet_Enabled, False) + self.queue_config.set(self.queue_config.queueSet_AfterAccomplish, "None") self.queue_config.set(self.queue_config.time_TimeEnabled_0, False) self.queue_config.set(self.queue_config.time_TimeSet_0, "00:00") @@ -542,8 +543,6 @@ class GlobalConfig(QConfig): function_IfSilence = ConfigItem("Function", "IfSilence", False, BoolValidator()) function_BossKey = ConfigItem("Function", "BossKey", "") - function_AutoShutdown = ConfigItem("Function", "AutoShutdown", False, BoolValidator()) - start_IfSelfStart = ConfigItem("Start", "IfSelfStart", False, BoolValidator()) start_IfRunDirectly = ConfigItem("Start", "IfRunDirectly", False, BoolValidator()) @@ -581,6 +580,12 @@ class QueueConfig(QConfig): queueSet_Name = ConfigItem("QueueSet", "Name", "") queueSet_Enabled = ConfigItem("QueueSet", "Enabled", False, BoolValidator()) + queueSet_AfterAccomplish = OptionsConfigItem( + "QueueSet", + "AfterAccomplish", + "None", + OptionsValidator(["None", "KillSelf", "Sleep", "Hibernate", "Shutdown"]), + ) time_TimeEnabled_0 = ConfigItem("Time", "TimeEnabled_0", False, BoolValidator()) time_TimeSet_0 = ConfigItem("Time", "TimeSet_0", "00:00") diff --git a/app/core/main_info_bar.py b/app/core/main_info_bar.py index 349df7e..c83f1ca 100644 --- a/app/core/main_info_bar.py +++ b/app/core/main_info_bar.py @@ -36,14 +36,14 @@ from qfluentwidgets import ( class _MainInfoBar: """信息通知栏""" - def __init__(self, parent=None): + def __init__(self, main_window=None): - self.parent = parent + self.main_window = main_window def push_info_bar(self, mode: str, title: str, content: str, time: int): """推送到信息通知栏""" - if self.parent is None: + if self.main_window is None: logger.error("信息通知栏未设置父窗口") return None @@ -55,7 +55,7 @@ class _MainInfoBar: isClosable=True, position=InfoBarPosition.TOP_RIGHT, duration=time, - parent=self.parent, + parent=self.main_window, ) elif mode == "warning": InfoBar.warning( @@ -65,7 +65,7 @@ class _MainInfoBar: isClosable=True, position=InfoBarPosition.TOP_RIGHT, duration=time, - parent=self.parent, + parent=self.main_window, ) elif mode == "error": InfoBar.error( @@ -75,7 +75,7 @@ class _MainInfoBar: isClosable=True, position=InfoBarPosition.TOP_RIGHT, duration=time, - parent=self.parent, + parent=self.main_window, ) elif mode == "info": InfoBar.info( @@ -85,7 +85,7 @@ class _MainInfoBar: isClosable=True, position=InfoBarPosition.TOP_RIGHT, duration=time, - parent=self.parent, + parent=self.main_window, ) diff --git a/app/core/task_manager.py b/app/core/task_manager.py index 70ae791..28d9fcc 100644 --- a/app/core/task_manager.py +++ b/app/core/task_manager.py @@ -28,6 +28,7 @@ v4.2 from loguru import logger from PySide6.QtCore import QThread, QObject, Signal from qfluentwidgets import Dialog +import json from pathlib import Path from datetime import datetime from typing import Dict, Union @@ -35,6 +36,7 @@ from typing import Dict, Union from .config import Config from .main_info_bar import MainInfoBar from app.models import MaaManager +from app.services import System class Task(QThread): @@ -214,7 +216,7 @@ class TaskManager(QObject): self.task_list[name].push_info_bar.connect(MainInfoBar.push_info_bar) self.task_list[name].update_user_info.connect(Config.change_user_info) self.task_list[name].accomplish.connect( - lambda logs: self.remove_task(name, logs) + lambda logs: self.remove_task(mode, name, logs) ) if "新调度台" in mode: @@ -247,8 +249,8 @@ class TaskManager(QObject): self.task_list[name].quit() self.task_list[name].wait() - def remove_task(self, name: str, logs: str): - """移除任务标记""" + def remove_task(self, mode: str, name: str, logs: str): + """任务结束后的处理""" logger.info(f"任务结束:{name}") MainInfoBar.push_info_bar("info", "任务结束", name, 3000) @@ -274,6 +276,13 @@ class TaskManager(QObject): self.task_list.pop(name) Config.running_list.remove(name) + if "调度队列" in name and "人工排查" not in mode: + with (Config.app_path / f"config/QueueConfig/{name}.json").open( + "r", encoding="utf-8" + ) as f: + info = json.load(f) + System.set_power(info["QueueSet"]["AfterAccomplish"]) + def push_dialog(self, name: str, title: str, content: str): """推送对话框""" diff --git a/app/models/MAA.py b/app/models/MAA.py index 92e7ba1..9536b79 100644 --- a/app/models/MAA.py +++ b/app/models/MAA.py @@ -539,13 +539,6 @@ class MaaManager(QObject): f"{self.mode[:4]}任务报告", f"{end_log}AUTO_MAA 敬上", ) - if Config.global_config.function_AutoShutdown: - logger.info("任务完成,系统将在 60 秒后自动关机...") - if sys.platform.startswith("win"): - subprocess.run("shutdown /s /t 60", shell=True) # Windows - else: - # 看到 Issues 里有兼容 Linux 的计划,加上 Linux 的 - subprocess.run("shutdown -h +1", shell=True) # Linux/macOS self.accomplish.emit({"Time": begin_time, "History": end_log}) diff --git a/app/services/system.py b/app/services/system.py index 8099229..b2939d2 100644 --- a/app/services/system.py +++ b/app/services/system.py @@ -25,21 +25,27 @@ v4.2 作者:DLmaster_361 """ +from loguru import logger +from PySide6.QtWidgets import QWidget +import sys import ctypes import win32gui import win32process import winreg import psutil +import subprocess from app.core import Config -class SystemHandler: +class _SystemHandler: ES_CONTINUOUS = 0x80000000 ES_SYSTEM_REQUIRED = 0x00000001 - def __init__(self): + def __init__(self, main_window: QWidget = None): + + self.main_window = main_window self.set_Sleep() self.set_SelfStart() @@ -84,6 +90,60 @@ class SystemHandler: winreg.DeleteValue(key, "AUTO_MAA") winreg.CloseKey(key) + def set_power(self, mode): + + if sys.platform.startswith("win"): + + if mode == "None": + + logger.info("不执行系统电源操作") + + elif mode == "Shutdown": + + logger.info("执行关机操作") + subprocess.run(["shutdown", "/s", "/t", "0"]) + + elif mode == "Hibernate": + + logger.info("执行休眠操作") + subprocess.run(["shutdown", "/h"]) + + elif mode == "Sleep": + + logger.info("执行睡眠操作") + subprocess.run( + ["rundll32.exe", "powrprof.dll,SetSuspendState", "0,1,0"] + ) + + elif mode == "KillSelf": + + self.main_window.close() + + elif sys.platform.startswith("linux"): + + if mode == "None": + + logger.info("不执行系统电源操作") + + elif mode == "Shutdown": + + logger.info("执行关机操作") + subprocess.run(["shutdown", "-h", "now"]) + + elif mode == "Hibernate": + + logger.info("执行休眠操作") + subprocess.run(["systemctl", "hibernate"]) + + elif mode == "Sleep": + + logger.info("执行睡眠操作") + subprocess.run(["systemctl", "suspend"]) + + elif mode == "KillSelf": + + self.main_window.close() + def is_startup(self): """判断程序是否已经开机自启""" @@ -117,4 +177,4 @@ class SystemHandler: return window_info -System = SystemHandler() +System = _SystemHandler() diff --git a/app/ui/dispatch_center.py b/app/ui/dispatch_center.py index d8161e9..af073e0 100644 --- a/app/ui/dispatch_center.py +++ b/app/ui/dispatch_center.py @@ -286,7 +286,7 @@ class DispatchBox(QWidget): logger.info(f"用户添加任务:{name}") Task_manager.add_task( - f"{self.mode.currentText()}_主调度台", "用户自定义队列", info + f"{self.mode.currentText()}_主调度台", "自定义队列", info ) class DispatchInfoCard(HeaderCardWidget): diff --git a/app/ui/main_window.py b/app/ui/main_window.py index e5de864..efb49f7 100644 --- a/app/ui/main_window.py +++ b/app/ui/main_window.py @@ -68,7 +68,8 @@ class AUTO_MAA(MSFluentWindow): self.splashScreen = SplashScreen(self.windowIcon(), self) self.show_ui("显示主窗口", if_quick=True) - MainInfoBar.parent = self + MainInfoBar.main_window = self.window() + System.main_window = self.window() # 创建主窗口 self.setting = Setting(self) @@ -161,7 +162,7 @@ class AUTO_MAA(MSFluentWindow): # 退出主程序菜单项 self.tray_menu.addAction( - Action(FluentIcon.POWER_BUTTON, "退出主程序", triggered=self.kill_main) + Action(FluentIcon.POWER_BUTTON, "退出主程序", triggered=self.window().close) ) # 设置托盘菜单 @@ -264,11 +265,6 @@ class AUTO_MAA(MSFluentWindow): # 3, # ) - def kill_main(self) -> None: - """退出主程序""" - self.close() - QApplication.quit() - def show_ui(self, mode: str, if_quick: bool = False) -> None: """配置窗口状态""" diff --git a/app/ui/member_manager.py b/app/ui/member_manager.py index ed60c90..a90201e 100644 --- a/app/ui/member_manager.py +++ b/app/ui/member_manager.py @@ -124,7 +124,7 @@ class MemberManager(QWidget): """添加一个脚本实例""" choice = InputMessageBox( - self, + self.window(), "选择一个脚本类型并添加相应脚本实例", "选择脚本类型", "选择", @@ -170,7 +170,7 @@ class MemberManager(QWidget): choice = MessageBox( "确认", f"确定要删除 {name} 实例吗?", - self, + self.window(), ) if choice.exec(): @@ -296,7 +296,7 @@ class MemberManager(QWidget): if Config.PASSWORD == "": choice = InputMessageBox( - self, + self.window(), "请输入管理密钥", "管理密钥", "密码", @@ -691,7 +691,7 @@ class MaaSettingBox(QWidget): set_list = ["自定义基建"] choice = SetMessageBox( - self.parent().parent().parent().parent().parent().parent().parent(), + self.window(), "用户选项配置", ["选择要配置的用户", "选择要配置的选项"], [user_list, set_list], @@ -731,7 +731,7 @@ class MaaSettingBox(QWidget): set_list = ["MAA日常配置", "MAA剿灭配置"] choice = SetMessageBox( - self.parent().parent().parent().parent().parent().parent().parent(), + self.window(), "用户选项配置", ["选择要配置的用户", "选择要配置的选项"], [user_list, set_list], @@ -1273,15 +1273,7 @@ class MaaSettingBox(QWidget): choice = MessageBox( "确认", f"确定要删除用户 {data[0][0]} 吗?", - self.parent() - .parent() - .parent() - .parent() - .parent() - .parent() - .parent() - .parent() - .parent(), + self.window(), ) # 删除用户 @@ -1570,15 +1562,7 @@ class MaaSettingBox(QWidget): choice = MessageBox( "确认", f"确定要将用户 {data[0][0]} 转为{mode_list[1 - mode]}配置模式吗?", - self.parent() - .parent() - .parent() - .parent() - .parent() - .parent() - .parent() - .parent() - .parent(), + self.window(), ) # 切换用户 diff --git a/app/ui/queue_manager.py b/app/ui/queue_manager.py index 8ae4f5b..4004220 100644 --- a/app/ui/queue_manager.py +++ b/app/ui/queue_manager.py @@ -43,6 +43,7 @@ from qfluentwidgets import ( TextBrowser, CommandBar, SwitchSettingCard, + ComboBoxSettingCard, ) from PySide6.QtCore import Qt from typing import List @@ -138,7 +139,7 @@ class QueueManager(QWidget): choice = MessageBox( "确认", f"确定要删除 {name} 吗?", - self, + self.window(), ) if choice.exec(): @@ -412,9 +413,23 @@ class QueueMemberSettingBox(QWidget): "调度队列状态", Config.queue_config.queueSet_Enabled, ) + self.card_AfterAccomplish = ComboBoxSettingCard( + configItem=Config.queue_config.queueSet_AfterAccomplish, + icon=FluentIcon.POWER_BUTTON, + title="调度队列结束后", + content="选择调度队列结束后的操作", + texts=[ + "无动作", + "退出AUTO_MAA", + "睡眠(win系统需禁用休眠)", + "休眠", + "关机", + ], + ) Layout.addWidget(self.card_Name) Layout.addWidget(self.card_Enable) + Layout.addWidget(self.card_AfterAccomplish) self.viewLayout.addLayout(Layout) diff --git a/app/ui/setting.py b/app/ui/setting.py index 0f13450..dcfdd87 100644 --- a/app/ui/setting.py +++ b/app/ui/setting.py @@ -111,7 +111,7 @@ class Setting(QWidget): while True: choice = InputMessageBox( - self.parent().parent().parent(), + self.window(), "未检测到管理密钥,请设置您的管理密钥", "管理密钥", "密码", @@ -123,7 +123,7 @@ class Setting(QWidget): choice = MessageBox( "警告", "您没有设置管理密钥,无法使用本软件,请先设置管理密钥", - self.parent().parent().parent(), + self.window(), ) choice.cancelButton.hide() choice.buttonLayout.insertStretch(1) @@ -138,7 +138,7 @@ class Setting(QWidget): while if_change: choice = InputMessageBox( - self, + self.window(), "请输入旧的管理密钥", "旧管理密钥", "密码", @@ -153,7 +153,7 @@ class Setting(QWidget): while True: choice = InputMessageBox( - self, + self.window(), "请输入新的管理密钥", "新管理密钥", "密码", @@ -173,14 +173,14 @@ class Setting(QWidget): choice = MessageBox( "确认", "您没有输入新的管理密钥,是否取消修改管理密钥?", - self, + self.window(), ) if choice.exec(): if_change = False break else: - choice = MessageBox("错误", "管理密钥错误", self) + choice = MessageBox("错误", "管理密钥错误", self.window()) choice.cancelButton.hide() choice.buttonLayout.insertStretch(1) if choice.exec(): @@ -189,7 +189,7 @@ class Setting(QWidget): choice = MessageBox( "确认", "您没有输入管理密钥,是否取消修改管理密钥?", - self, + self.window(), ) if choice.exec(): break @@ -261,7 +261,7 @@ class Setting(QWidget): choice = MessageBox( "错误", f"获取版本信息时出错:\n{err}", - self, + self.window(), ) choice.cancelButton.hide() choice.buttonLayout.insertStretch(1) @@ -297,7 +297,7 @@ class Setting(QWidget): choice = MessageBox( "版本更新", f"发现新版本:\n{main_version_info}{updater_version_info} 更新说明:\n{version_remote['announcement'].replace("\n# ","\n !").replace("\n## ","\n - ").replace("\n- ","\n · ")}\n\n是否开始更新?\n\n 注意:主程序更新时AUTO_MAA将自动关闭", - self, + self.window(), ) if not choice.exec(): return None @@ -399,20 +399,11 @@ class FunctionSettingCard(HeaderCardWidget): content="仅阻止电脑自动休眠,不会影响屏幕是否熄灭", configItem=Config.global_config.function_IfAllowSleep, ) - - self.card_AutoShutdown = SwitchSettingCard( - icon=FluentIcon.POWER_BUTTON, - title="运行完成后自动关机", - content="启用后,任务完成后将自动关机", - configItem=Config.global_config.function_AutoShutdown, - ) - self.card_IfSilence = self.SilenceSettingCard(self) Layout = QVBoxLayout() Layout.addWidget(self.card_IfAllowSleep) Layout.addWidget(self.card_IfSilence) - Layout.addWidget(self.card_AutoShutdown) self.viewLayout.addLayout(Layout) class SilenceSettingCard(ExpandGroupSettingCard): @@ -762,7 +753,3 @@ def version_text(version_numb: list) -> str: f"v{'.'.join(str(_) for _ in version_numb[0:3])}-beta.{version_numb[3]}" ) return version - -def toggle_auto_shutdown(self, checked: bool) -> None: - """启用或禁用自动关机""" - Config.global_config.function_AutoShutdown = checked diff --git a/resources/version.json b/resources/version.json index a957e16..1f5706b 100644 --- a/resources/version.json +++ b/resources/version.json @@ -1,7 +1,7 @@ { - "main_version": "4.2.2.2", + "main_version": "4.2.2.3", "updater_version": "1.1.1.3", - "announcement": "\n## 新增功能\n- 添加用户每日代理次数上限功能 #15\n- 新增代理成功消息推送渠道Server酱与企业微信群机器人推送\n- 添加更新类别可选项\n## 修复BUG\n- 修复自定义基建无法正常使用的问题\n- 修正人工排查文案\n- 修复高级MAA配置序号错位\n- 修复高级用户列表无法配置问题\n- 修复主调度台选项乱动问题\n- 修复更新器文件夹定位问题\n## 程序优化\n- 无", + "announcement": "\n## 新增功能\n- 添加用户每日代理次数上限功能 #15\n- 新增代理成功消息推送渠道Server酱与企业微信群机器人推送\n- 添加更新类别可选项\n- 添加调度队列完成任务后行为选项\n## 修复BUG\n- 修复自定义基建无法正常使用的问题\n- 修正人工排查文案\n- 修复高级MAA配置序号错位\n- 修复高级用户列表无法配置问题\n- 修复主调度台选项乱动问题\n- 修复更新器文件夹定位问题\n## 程序优化\n- 优化弹窗逻辑", "proxy_list": [ "", "https://gitproxy.click/",