Merge commit '4efbafc174504bd2fbd5b22075e3b5429406691b' into generic_dev

This commit is contained in:
DLmaster361
2025-07-12 19:41:10 +08:00
8 changed files with 271 additions and 113 deletions

View File

@@ -706,7 +706,7 @@ class GeneralSubConfig(LQConfig):
class AppConfig(GlobalConfig): class AppConfig(GlobalConfig):
VERSION = "4.4.0.3" VERSION = "4.4.0.5"
stage_refreshed = Signal() stage_refreshed = Signal()
PASSWORD_refreshed = Signal() PASSWORD_refreshed = Signal()
@@ -717,7 +717,7 @@ class AppConfig(GlobalConfig):
super().__init__() super().__init__()
self.app_path = Path(sys.argv[0]).resolve().parent # 获取软件根目录 self.app_path = Path(sys.argv[0]).resolve().parent # 获取软件根目录
self.app_path_sys = str(Path(sys.argv[0]).resolve()) # 获取软件自身的路径 self.app_path_sys = Path(sys.argv[0]).resolve() # 获取软件自身的路径
self.log_path = self.app_path / "debug/AUTO_MAA.log" self.log_path = self.app_path / "debug/AUTO_MAA.log"
self.database_path = self.app_path / "data/data.db" self.database_path = self.app_path / "data/data.db"
@@ -1081,57 +1081,66 @@ class AppConfig(GlobalConfig):
logger.info("数据文件版本更新v1.6-->v1.7") logger.info("数据文件版本更新v1.6-->v1.7")
if_streaming = True if_streaming = True
for MaaConfig in (self.app_path / "config/MaaConfig").iterdir(): if (self.app_path / "config/MaaConfig").exists():
if MaaConfig.is_dir():
for user in (MaaConfig / "UserData").iterdir():
if user.is_dir():
if (user / "config.json").exists():
with (user / "config.json").open(
encoding="utf-8"
) as f:
user_config = json.load(f)
user_config["Info"]["Stage"] = user_config["Info"][
"GameId"
]
user_config["Info"]["StageMode"] = user_config[
"Info"
]["GameIdMode"]
user_config["Info"]["Stage_1"] = user_config[
"Info"
]["GameId_1"]
user_config["Info"]["Stage_2"] = user_config[
"Info"
]["GameId_2"]
user_config["Info"]["Stage_Remain"] = user_config[
"Info"
]["GameId_Remain"]
with (user / "config.json").open(
"w", encoding="utf-8"
) as f:
json.dump(
user_config, f, ensure_ascii=False, indent=4
)
for MaaPlanConfig in (self.app_path / "config/MaaPlanConfig").iterdir():
if (
MaaPlanConfig.is_dir()
and (MaaPlanConfig / "config.json").exists()
):
with (MaaPlanConfig / "config.json").open(
encoding="utf-8"
) as f:
plan_config = json.load(f)
for k in self.stage_dict.keys(): for MaaConfig in (self.app_path / "config/MaaConfig").iterdir():
plan_config[k]["Stage"] = plan_config[k]["GameId"] if MaaConfig.is_dir():
plan_config[k]["Stage_1"] = plan_config[k]["GameId_1"] for user in (MaaConfig / "UserData").iterdir():
plan_config[k]["Stage_2"] = plan_config[k]["GameId_2"] if user.is_dir():
plan_config[k]["Stage_Remain"] = plan_config[k][ if (user / "config.json").exists():
"GameId_Remain" with (user / "config.json").open(
] encoding="utf-8"
with (MaaPlanConfig / "config.json").open( ) as f:
"w", encoding="utf-8" user_config = json.load(f)
) as f: user_config["Info"]["Stage"] = user_config[
json.dump(plan_config, f, ensure_ascii=False, indent=4) "Info"
]["GameId"]
user_config["Info"]["StageMode"] = user_config[
"Info"
]["GameIdMode"]
user_config["Info"]["Stage_1"] = user_config[
"Info"
]["GameId_1"]
user_config["Info"]["Stage_2"] = user_config[
"Info"
]["GameId_2"]
user_config["Info"]["Stage_Remain"] = (
user_config["Info"]["GameId_Remain"]
)
with (user / "config.json").open(
"w", encoding="utf-8"
) as f:
json.dump(
user_config,
f,
ensure_ascii=False,
indent=4,
)
if (self.app_path / "config/MaaPlanConfig").exists():
for MaaPlanConfig in (
self.app_path / "config/MaaPlanConfig"
).iterdir():
if (
MaaPlanConfig.is_dir()
and (MaaPlanConfig / "config.json").exists()
):
with (MaaPlanConfig / "config.json").open(
encoding="utf-8"
) as f:
plan_config = json.load(f)
for k in self.stage_dict.keys():
plan_config[k]["Stage"] = plan_config[k]["GameId"]
plan_config[k]["Stage_1"] = plan_config[k]["GameId_1"]
plan_config[k]["Stage_2"] = plan_config[k]["GameId_2"]
plan_config[k]["Stage_Remain"] = plan_config[k][
"GameId_Remain"
]
with (MaaPlanConfig / "config.json").open(
"w", encoding="utf-8"
) as f:
json.dump(plan_config, f, ensure_ascii=False, indent=4)
cur.execute("DELETE FROM version WHERE v = ?", ("v1.6",)) cur.execute("DELETE FROM version WHERE v = ?", ("v1.6",))
cur.execute("INSERT INTO version VALUES(?)", ("v1.7",)) cur.execute("INSERT INTO version VALUES(?)", ("v1.7",))

View File

@@ -147,22 +147,36 @@ class CryptoHandler:
for member in Config.member_dict.values(): for member in Config.member_dict.values():
# 使用旧管理密钥解密 # 使用旧管理密钥解密
for user in member["UserData"].values(): if member["Type"] == "Maa":
user["Password"] = self.AUTO_decryptor( for user in member["UserData"].values():
user["Config"].get(user["Config"].Info_Password), PASSWORD_old user["Password"] = self.AUTO_decryptor(
) user["Config"].get(user["Config"].Info_Password), PASSWORD_old
)
self.get_PASSWORD(PASSWORD_new) self.get_PASSWORD(PASSWORD_new)
for member in Config.member_dict.values(): for member in Config.member_dict.values():
# 使用新管理密钥重新加密 # 使用新管理密钥重新加密
for user in member["UserData"].values(): if member["Type"] == "Maa":
user["Config"].set( for user in member["UserData"].values():
user["Config"].Info_Password, self.AUTO_encryptor(user["Password"]) user["Config"].set(
) user["Config"].Info_Password,
user["Password"] = None self.AUTO_encryptor(user["Password"]),
del user["Password"] )
user["Password"] = None
del user["Password"]
def reset_PASSWORD(self, PASSWORD_new: str) -> None:
"""重置管理密钥"""
self.get_PASSWORD(PASSWORD_new)
for member in Config.member_dict.values():
if member["Type"] == "Maa":
for user in member["UserData"].values():
user["Config"].set(user["Config"].Info_Password, "")
def win_encryptor( def win_encryptor(
self, note: str, description: str = None, entropy: bytes = None self, note: str, description: str = None, entropy: bytes = None

View File

@@ -31,9 +31,11 @@ import sys
import ctypes import ctypes
import win32gui import win32gui
import win32process import win32process
import winreg
import psutil import psutil
import subprocess import subprocess
import tempfile
import getpass
from datetime import datetime
from pathlib import Path from pathlib import Path
from app.core import Config from app.core import Config
@@ -61,44 +63,103 @@ class _SystemHandler:
# 恢复系统电源状态 # 恢复系统电源状态
ctypes.windll.kernel32.SetThreadExecutionState(self.ES_CONTINUOUS) ctypes.windll.kernel32.SetThreadExecutionState(self.ES_CONTINUOUS)
def set_SelfStart(self) -> bool: def set_SelfStart(self) -> None:
"""同步开机自启""" """同步开机自启"""
if Config.get(Config.start_IfSelfStart) and not self.is_startup(): if Config.get(Config.start_IfSelfStart) and not self.is_startup():
# 创建任务计划
try: try:
# 创建任务计划 # 获取当前用户和时间
result = subprocess.run( current_user = getpass.getuser()
[ current_time = datetime.now().strftime("%Y-%m-%dT%H:%M:%S")
"schtasks",
"/create",
"/tn",
"AUTO_MAA_AutoStart",
"/tr",
Config.app_path_sys,
"/sc",
"onlogon",
"/rl",
"highest", # 以最高权限运行
"/f", # 强制创建(覆盖现有任务)
],
creationflags=subprocess.CREATE_NO_WINDOW,
stdin=subprocess.DEVNULL,
capture_output=True,
text=True,
)
if result.returncode == 0: # XML 模板
logger.info(f"任务计划程序自启动已创建: {Config.app_path_sys}") xml_content = f"""<?xml version="1.0" encoding="UTF-16"?>
return True <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
else: <RegistrationInfo>
logger.error(f"创建任务计划失败: {result.stderr}") <Date>{current_time}</Date>
return False <Author>{current_user}</Author>
<Description>AUTO_MAA自启动服务</Description>
<URI>\\AUTO_MAA_AutoStart</URI>
</RegistrationInfo>
<Triggers>
<LogonTrigger>
<StartBoundary>{current_time}</StartBoundary>
<Enabled>true</Enabled>
</LogonTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<LogonType>InteractiveToken</LogonType>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
<AllowHardTerminate>false</AllowHardTerminate>
<StartWhenAvailable>true</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>false</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>"{Config.app_path_sys}"</Command>
</Exec>
</Actions>
</Task>"""
# 创建临时 XML 文件并执行
with tempfile.NamedTemporaryFile(
mode="w", suffix=".xml", delete=False, encoding="utf-16"
) as f:
f.write(xml_content)
xml_file = f.name
try:
result = subprocess.run(
[
"schtasks",
"/create",
"/tn",
"AUTO_MAA_AutoStart",
"/xml",
xml_file,
"/f",
],
creationflags=subprocess.CREATE_NO_WINDOW,
stdin=subprocess.DEVNULL,
capture_output=True,
text=True,
)
if result.returncode == 0:
logger.info(f"任务计划程序自启动已创建: {Config.app_path_sys}")
else:
logger.error(f"创建任务计划失败: {result.stderr}")
finally:
# 删除临时文件
try:
Path(xml_file).unlink()
except:
pass
except Exception as e: except Exception as e:
logger.error(f"设置任务计划程序自启动失败: {e}") logger.exception(f"设置任务计划程序自启动失败: {e}")
return False
elif not Config.get(Config.start_IfSelfStart) and self.is_startup(): elif not Config.get(Config.start_IfSelfStart) and self.is_startup():
@@ -114,14 +175,11 @@ class _SystemHandler:
if result.returncode == 0: if result.returncode == 0:
logger.info("任务计划程序自启动已删除") logger.info("任务计划程序自启动已删除")
return True
else: else:
logger.error(f"删除任务计划失败: {result.stderr}") logger.error(f"删除任务计划失败: {result.stderr}")
return False
except Exception as e: except Exception as e:
logger.error(f"删除任务计划程序自启动失败: {e}") logger.exception(f"删除任务计划程序自启动失败: {e}")
return False
def set_power(self, mode) -> None: def set_power(self, mode) -> None:

View File

@@ -469,7 +469,7 @@ class AUTO_MAA(MSFluentWindow):
logger.warning("启动主任务失败:未找到有效的主任务配置文件") logger.warning("启动主任务失败:未找到有效的主任务配置文件")
MainInfoBar.push_info_bar( MainInfoBar.push_info_bar(
"warning", "启动主任务失败", "调度队列_1”与“脚本_1均不存在", -1 "warning", "启动主任务失败", "调度队列_1」与「脚本_1均不存在", -1
) )
def __currentChanged(self, index: int) -> None: def __currentChanged(self, index: int) -> None:

View File

@@ -804,7 +804,7 @@ class MemberManager(QWidget):
self.card_TaskTransitionMethod = ComboBoxSettingCard( self.card_TaskTransitionMethod = ComboBoxSettingCard(
icon=FluentIcon.PAGE_RIGHT, icon=FluentIcon.PAGE_RIGHT,
title="任务切换方式", title="任务切换方式",
content="相邻两个任务间的切换方式,使用详细配置的用户固定为重启模拟器", content="相邻两个任务间的切换方式,使用详细配置的用户固定为重启模拟器",
texts=["直接切换账号", "重启明日方舟", "重启模拟器"], texts=["直接切换账号", "重启明日方舟", "重启模拟器"],
qconfig=self.config, qconfig=self.config,
configItem=self.config.RunSet_TaskTransitionMethod, configItem=self.config.RunSet_TaskTransitionMethod,
@@ -813,7 +813,7 @@ class MemberManager(QWidget):
self.card_ProxyTimesLimit = SpinBoxSettingCard( self.card_ProxyTimesLimit = SpinBoxSettingCard(
icon=FluentIcon.PAGE_RIGHT, icon=FluentIcon.PAGE_RIGHT,
title="用户单日代理次数上限", title="用户单日代理次数上限",
content="当用户本日代理成功次数达到该阈值时跳过代理,阈值为“0”时视为无代理次数上限", content="当用户本日代理成功次数达到该阈值时跳过代理,阈值为「0」时视为无代理次数上限",
range=(0, 1024), range=(0, 1024),
qconfig=self.config, qconfig=self.config,
configItem=self.config.RunSet_ProxyTimesLimit, configItem=self.config.RunSet_ProxyTimesLimit,
@@ -2187,7 +2187,7 @@ class MemberManager(QWidget):
self.card_ServerChanChannel = LineEditSettingCard( self.card_ServerChanChannel = LineEditSettingCard(
icon=FluentIcon.PAGE_RIGHT, icon=FluentIcon.PAGE_RIGHT,
title="用户ServerChanChannel代码", title="用户ServerChanChannel代码",
content="留空则默认,多个请使用“|”隔开", content="留空则默认,多个请使用「|」隔开",
text="请输入Channel代码仅SCT生效", text="请输入Channel代码仅SCT生效",
qconfig=self.config, qconfig=self.config,
configItem=self.config.Notify_ServerChanChannel, configItem=self.config.Notify_ServerChanChannel,
@@ -2196,7 +2196,7 @@ class MemberManager(QWidget):
self.card_ServerChanTag = LineEditSettingCard( self.card_ServerChanTag = LineEditSettingCard(
icon=FluentIcon.PAGE_RIGHT, icon=FluentIcon.PAGE_RIGHT,
title="用户Tag内容", title="用户Tag内容",
content="留空则默认,多个请使用“|”隔开", content="留空则默认,多个请使用「|」隔开",
text="请输入加入推送的Tag仅SC3生效", text="请输入加入推送的Tag仅SC3生效",
qconfig=self.config, qconfig=self.config,
configItem=self.config.Notify_ServerChanTag, configItem=self.config.Notify_ServerChanTag,
@@ -2404,7 +2404,7 @@ class MemberManager(QWidget):
self.card_SuccessLog = LineEditSettingCard( self.card_SuccessLog = LineEditSettingCard(
icon=FluentIcon.PAGE_RIGHT, icon=FluentIcon.PAGE_RIGHT,
title="脚本成功日志", title="脚本成功日志",
content="任务成功完成时出现的日志,多条请使用“|”隔开", content="任务成功完成时出现的日志,多条请使用「|」隔开",
text="请输入脚本成功日志内容", text="请输入脚本成功日志内容",
qconfig=self.config, qconfig=self.config,
configItem=self.config.Script_SuccessLog, configItem=self.config.Script_SuccessLog,
@@ -2413,7 +2413,7 @@ class MemberManager(QWidget):
self.card_ErrorLog = LineEditSettingCard( self.card_ErrorLog = LineEditSettingCard(
icon=FluentIcon.PAGE_RIGHT, icon=FluentIcon.PAGE_RIGHT,
title="脚本异常日志 - [必填]", title="脚本异常日志 - [必填]",
content="脚本运行异常时的日志内容,多条请使用“|”隔开", content="脚本运行异常时的日志内容,多条请使用「|」隔开",
text="请输入脚本异常日志内容", text="请输入脚本异常日志内容",
qconfig=self.config, qconfig=self.config,
configItem=self.config.Script_ErrorLog, configItem=self.config.Script_ErrorLog,
@@ -2580,7 +2580,7 @@ class MemberManager(QWidget):
self.card_ProxyTimesLimit = SpinBoxSettingCard( self.card_ProxyTimesLimit = SpinBoxSettingCard(
icon=FluentIcon.PAGE_RIGHT, icon=FluentIcon.PAGE_RIGHT,
title="子配置单日代理次数上限", title="子配置单日代理次数上限",
content="当子配置本日代理成功次数达到该阈值时跳过代理,阈值为“0”时视为无代理次数上限", content="当子配置本日代理成功次数达到该阈值时跳过代理,阈值为「0」时视为无代理次数上限",
range=(0, 1024), range=(0, 1024),
qconfig=self.config, qconfig=self.config,
configItem=self.config.Run_ProxyTimesLimit, configItem=self.config.Run_ProxyTimesLimit,
@@ -3339,7 +3339,7 @@ class MemberManager(QWidget):
self.card_ServerChanChannel = LineEditSettingCard( self.card_ServerChanChannel = LineEditSettingCard(
icon=FluentIcon.PAGE_RIGHT, icon=FluentIcon.PAGE_RIGHT,
title="用户ServerChanChannel代码", title="用户ServerChanChannel代码",
content="留空则默认,多个请使用“|”隔开", content="留空则默认,多个请使用「|」隔开",
text="请输入Channel代码仅SCT生效", text="请输入Channel代码仅SCT生效",
qconfig=self.config, qconfig=self.config,
configItem=self.config.Notify_ServerChanChannel, configItem=self.config.Notify_ServerChanChannel,
@@ -3348,7 +3348,7 @@ class MemberManager(QWidget):
self.card_ServerChanTag = LineEditSettingCard( self.card_ServerChanTag = LineEditSettingCard(
icon=FluentIcon.PAGE_RIGHT, icon=FluentIcon.PAGE_RIGHT,
title="用户Tag内容", title="用户Tag内容",
content="留空则默认,多个请使用“|”隔开", content="留空则默认,多个请使用「|」隔开",
text="请输入加入推送的Tag仅SC3生效", text="请输入加入推送的Tag仅SC3生效",
qconfig=self.config, qconfig=self.config,
configItem=self.config.Notify_ServerChanTag, configItem=self.config.Notify_ServerChanTag,

View File

@@ -86,6 +86,7 @@ class Setting(QWidget):
) )
self.start.card_IfSelfStart.checkedChanged.connect(System.set_SelfStart) self.start.card_IfSelfStart.checkedChanged.connect(System.set_SelfStart)
self.security.card_changePASSWORD.clicked.connect(self.change_PASSWORD) self.security.card_changePASSWORD.clicked.connect(self.change_PASSWORD)
self.security.card_resetPASSWORD.clicked.connect(self.reset_PASSWORD)
self.updater.card_CheckUpdate.clicked.connect( self.updater.card_CheckUpdate.clicked.connect(
lambda: self.check_update(if_show=True) lambda: self.check_update(if_show=True)
) )
@@ -119,7 +120,7 @@ class Setting(QWidget):
choice = MessageBox( choice = MessageBox(
"授权声明", "授权声明",
"开启托管bilibili游戏隐私政策功能即代表您已完整阅读并同意《哔哩哔哩弹幕网用户使用协议》、《哔哩哔哩隐私政策》和《哔哩哔哩游戏中心用户协议》并授权AUTO_MAA在其认定需要时以其认定合适的方法替您处理相关弹窗\n\n是否同意授权?", "开启托管bilibili游戏隐私政策功能即代表您已完整阅读并同意《哔哩哔哩弹幕网用户使用协议》、《哔哩哔哩隐私政策》和《哔哩哔哩游戏中心用户协议》并授权AUTO_MAA在其认定需要时以其认定合适的方法替您处理相关弹窗\n\n是否同意授权?",
self.window(), self.window(),
) )
if choice.exec(): if choice.exec():
@@ -147,7 +148,7 @@ class Setting(QWidget):
choice = MessageBox( choice = MessageBox(
"风险声明", "风险声明",
"开启跳过MuMu启动广告功能即代表您已安装MuMu模拟器-12且允许AUTO_MAA以其认定合适的方法屏蔽MuMu启动广告并接受此操作带来的风险\n\n此功能即时生效,是否仍要开启此功能?", "开启跳过MuMu启动广告功能即代表您已安装MuMu模拟器-12且允许AUTO_MAA以其认定合适的方法屏蔽MuMu启动广告并接受此操作带来的风险\n\n此功能即时生效,是否仍要开启此功能?",
self.window(), self.window(),
) )
if choice.exec(): if choice.exec():
@@ -259,6 +260,61 @@ class Setting(QWidget):
if choice.exec(): if choice.exec():
break break
def reset_PASSWORD(self) -> None:
"""重置管理密钥"""
choice = MessageBox(
"确认",
"重置管理密钥将清空所有使用管理密钥加密的数据,您确认要重置管理密钥吗?",
self.window(),
)
if choice.exec():
choice = LineEditMessageBox(
self.window(),
"请输入文本提示框内的验证信息",
"AUTO_MAA绝赞DeBug中",
"明文",
)
if choice.exec() and choice.input.text() in [
"AUTO_MAA绝赞DeBug中",
"AUTO_MAA绝赞DeBug中!",
]:
# 获取新的管理密钥
while True:
choice = LineEditMessageBox(
self.window(), "请输入新的管理密钥", "新管理密钥", "密码"
)
if choice.exec() and choice.input.text() != "":
# 重置管理密钥
Crypto.reset_PASSWORD(choice.input.text())
MainInfoBar.push_info_bar(
"success", "操作成功", "管理密钥重置成功", 3000
)
break
else:
choice = MessageBox(
"确认",
"您没有输入新的管理密钥,是否取消修改管理密钥?",
self.window(),
)
if choice.exec():
break
else:
MainInfoBar.push_info_bar(
"info",
"验证未通过",
"请输入「AUTO_MAA绝赞DeBug中」后单击确认键",
3000,
)
def check_update(self, if_show: bool = False, if_first: bool = False) -> None: def check_update(self, if_show: bool = False, if_first: bool = False) -> None:
"""检查版本更新,调起文件下载进程""" """检查版本更新,调起文件下载进程"""
@@ -670,7 +726,7 @@ class FunctionSettingCard(HeaderCardWidget):
self.card_BossKey = LineEditSettingCard( self.card_BossKey = LineEditSettingCard(
icon=FluentIcon.PAGE_RIGHT, icon=FluentIcon.PAGE_RIGHT,
title="模拟器老板键", title="模拟器老板键",
content="请输入对应的模拟器老板键,请直接输入文字,多个键位之间请用“+”隔开。如:Alt+Q", content="请输入对应的模拟器老板键,请直接输入文字,多个键位之间请用「+」隔开。如:Alt+Q",
text="请以文字形式输入模拟器老板快捷键", text="请以文字形式输入模拟器老板快捷键",
qconfig=Config, qconfig=Config,
configItem=Config.function_BossKey, configItem=Config.function_BossKey,
@@ -981,7 +1037,7 @@ class NotifySettingCard(HeaderCardWidget):
self.card_ServerChanChannel = LineEditSettingCard( self.card_ServerChanChannel = LineEditSettingCard(
icon=FluentIcon.PAGE_RIGHT, icon=FluentIcon.PAGE_RIGHT,
title="ServerChanChannel代码", title="ServerChanChannel代码",
content="可以留空,留空则默认。可以多个,请使用“|”隔开", content="可以留空,留空则默认。可以多个,请使用「|」隔开",
text="请输入需要推送的Channel代码SCT生效", text="请输入需要推送的Channel代码SCT生效",
qconfig=Config, qconfig=Config,
configItem=Config.notify_ServerChanChannel, configItem=Config.notify_ServerChanChannel,
@@ -990,7 +1046,7 @@ class NotifySettingCard(HeaderCardWidget):
self.card_ServerChanTag = LineEditSettingCard( self.card_ServerChanTag = LineEditSettingCard(
icon=FluentIcon.PAGE_RIGHT, icon=FluentIcon.PAGE_RIGHT,
title="Tag内容", title="Tag内容",
content="可以留空,留空则默认。可以多个,请使用“|”隔开", content="可以留空,留空则默认。可以多个,请使用「|」隔开",
text="请输入加入推送的TagSC3生效", text="请输入加入推送的TagSC3生效",
qconfig=Config, qconfig=Config,
configItem=Config.notify_ServerChanTag, configItem=Config.notify_ServerChanTag,
@@ -1056,9 +1112,17 @@ class SecuritySettingCard(HeaderCardWidget):
content="修改用于解密用户密码的管理密钥", content="修改用于解密用户密码的管理密钥",
parent=self, parent=self,
) )
self.card_resetPASSWORD = PushSettingCard(
text="重置",
icon=FluentIcon.VPN,
title="重置管理密钥",
content="重置用于解密用户密码的管理密钥",
parent=self,
)
Layout = QVBoxLayout() Layout = QVBoxLayout()
Layout.addWidget(self.card_changePASSWORD) Layout.addWidget(self.card_changePASSWORD)
Layout.addWidget(self.card_resetPASSWORD)
self.viewLayout.addLayout(Layout) self.viewLayout.addLayout(Layout)

View File

@@ -10,5 +10,5 @@ certifi==2025.4.26
requests==2.32.4 requests==2.32.4
markdown==3.8.2 markdown==3.8.2
Jinja2==3.1.6 Jinja2==3.1.6
nuitka==2.7.11 nuitka==2.7.12
pillow==11.3.0 pillow==11.3.0

View File

@@ -1,6 +1,19 @@
{ {
"main_version": "4.4.0.3", "main_version": "4.4.0.5",
"version_info": { "version_info": {
"4.4.0.5": {
"修复BUG": [
"修复开机自启相关功能"
]
},
"4.4.0.4": {
"新增功能": [
"添加重置管理密钥功能"
],
"修复BUG": [
"修复无计划表时数据系统无法正常升级到v1.7的问题"
]
},
"4.4.0.3": { "4.4.0.3": {
"修复BUG": [ "修复BUG": [
"适配 MAA 备选关卡字段修改", "适配 MAA 备选关卡字段修改",