diff --git a/app/core/config.py b/app/core/config.py index 6070b52..c27f409 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -388,9 +388,7 @@ class MaaUserConfig(LQConfig): self.Info_Mode = OptionsConfigItem( "Info", "Mode", "简洁", OptionsValidator(["简洁", "详细"]) ) - self.Info_GameIdMode = OptionsConfigItem( - "Info", "GameIdMode", "固定", OptionsValidator(["固定"]) - ) + self.Info_GameIdMode = ConfigItem("Info", "GameIdMode", "固定") self.Info_Server = OptionsConfigItem( "Info", "Server", "Official", OptionsValidator(["Official", "Bilibili"]) ) @@ -461,6 +459,29 @@ class MaaUserConfig(LQConfig): "Notify", "CompanyWebHookBotUrl", "" ) + def get_plan_info(self) -> Dict[str, Union[str, int]]: + """获取当前的计划下信息""" + + if self.get(self.Info_GameIdMode) == "固定": + return { + "MedicineNumb": self.get(self.Info_MedicineNumb), + "SeriesNumb": self.get(self.Info_SeriesNumb), + "GameId": self.get(self.Info_GameId), + "GameId_1": self.get(self.Info_GameId_1), + "GameId_2": self.get(self.Info_GameId_2), + "GameId_Remain": self.get(self.Info_GameId_Remain), + } + elif "计划" in self.get(self.Info_GameIdMode): + plan = Config.plan_dict[self.get(self.Info_GameIdMode)]["Config"] + return { + "MedicineNumb": plan.get(plan.get_current_info("MedicineNumb")), + "SeriesNumb": plan.get(plan.get_current_info("SeriesNumb")), + "GameId": plan.get(plan.get_current_info("GameId")), + "GameId_1": plan.get(plan.get_current_info("GameId_1")), + "GameId_2": plan.get(plan.get_current_info("GameId_2")), + "GameId_Remain": plan.get(plan.get_current_info("GameId_Remain")), + } + class MaaPlanConfig(LQConfig): """MAA计划表配置""" @@ -468,7 +489,10 @@ class MaaPlanConfig(LQConfig): def __init__(self) -> None: super().__init__() - self.Info_Name = ConfigItem("Info", "Name", "新表格") + self.Info_Name = ConfigItem("Info", "Name", "") + self.Info_Mode = OptionsConfigItem( + "Info", "Mode", "ALL", OptionsValidator(["ALL", "Weekly"]) + ) self.config_item_dict: dict[str, Dict[str, ConfigItem]] = {} @@ -514,6 +538,18 @@ class MaaPlanConfig(LQConfig): ]: setattr(self, f"{group}_{name}", self.config_item_dict[group][name]) + def get_current_info(self, name: str) -> ConfigItem: + """获取当前的计划表配置项""" + + if self.get(self.Info_Mode) == "ALL": + return self.config_item_dict["ALL"][name] + elif self.get(self.Info_Mode) == "Weekly": + today = datetime.now().strftime("%A") + if today in self.config_item_dict: + return self.config_item_dict[today][name] + else: + return self.config_item_dict["ALL"][name] + class AppConfig(GlobalConfig): @@ -615,7 +651,7 @@ class AppConfig(GlobalConfig): logger.warning(f"无法从MAA服务器获取活动关卡信息:{Network.error_message}") gameid_infos = [] - gameid_dict = {"value": [], "text": []} + ss_gameid_dict = {"value": [], "text": []} for gameid_info in gameid_infos: @@ -628,85 +664,48 @@ class AppConfig(GlobalConfig): gameid_info["Activity"]["UtcExpireTime"], "%Y/%m/%d %H:%M:%S" ) ): - gameid_dict["value"].append(gameid_info["Value"]) - gameid_dict["text"].append(gameid_info["Value"]) - - # 生成全部关卡信息 - self.gameid_dict["ALL"]["value"] = gameid_dict["value"] + [ - "-", - "1-7", - "R8-11", - "12-17-HARD", - "CE-6", - "AP-5", - "CA-5", - "LS-6", - "SK-5", - "PR-A-1", - "PR-A-2", - "PR-B-1", - "PR-B-2", - "PR-C-1", - "PR-C-2", - "PR-D-1", - "PR-D-2", - ] - self.gameid_dict["ALL"]["text"] = gameid_dict["text"] + [ - "当前/上次", - "1-7", - "R8-11", - "12-17-HARD", - "龙门币-6/5", - "红票-5", - "技能-5", - "经验-6/5", - "碳-5", - "奶/盾芯片", - "奶/盾芯片组", - "术/狙芯片", - "术/狙芯片组", - "先/辅芯片", - "先/辅芯片组", - "近/特芯片", - "近/特芯片组", - ] - - # # 生成本日关卡信息 - # days = self.server_date().isoweekday() + ss_gameid_dict["value"].append(gameid_info["Value"]) + ss_gameid_dict["text"].append(gameid_info["Value"]) # 生成每日关卡信息 - for day in range(1, 8): + gameid_daily_info = [ + {"value": "-", "text": "当前/上次", "days": [1, 2, 3, 4, 5, 6, 7]}, + {"value": "1-7", "text": "1-7", "days": [1, 2, 3, 4, 5, 6, 7]}, + {"value": "R8-11", "text": "R8-11", "days": [1, 2, 3, 4, 5, 6, 7]}, + { + "value": "12-17-HARD", + "text": "12-17-HARD", + "days": [1, 2, 3, 4, 5, 6, 7], + }, + {"value": "CE-6", "text": "龙门币-6/5", "days": [2, 4, 6, 7]}, + {"value": "AP-5", "text": "红票-5", "days": [1, 4, 6, 7]}, + {"value": "CA-5", "text": "技能-5", "days": [2, 3, 5, 7]}, + {"value": "LS-6", "text": "经验-6/5", "days": [1, 2, 3, 4, 5, 6, 7]}, + {"value": "SK-5", "text": "碳-5", "days": [1, 3, 5, 6]}, + {"value": "PR-A-1", "text": "奶/盾芯片", "days": [1, 4, 5, 7]}, + {"value": "PR-A-2", "text": "奶/盾芯片组", "days": [1, 4, 5, 7]}, + {"value": "PR-B-1", "text": "术/狙芯片", "days": [1, 2, 5, 6]}, + {"value": "PR-B-2", "text": "术/狙芯片组", "days": [1, 2, 5, 6]}, + {"value": "PR-C-1", "text": "先/辅芯片", "days": [3, 4, 6, 7]}, + {"value": "PR-C-2", "text": "先/辅芯片组", "days": [3, 4, 6, 7]}, + {"value": "PR-D-1", "text": "近/特芯片", "days": [2, 3, 6, 7]}, + {"value": "PR-D-2", "text": "近/特芯片组", "days": [2, 3, 6, 7]}, + ] - gameid_list = [ - {"value": "-", "text": "当前/上次", "days": [1, 2, 3, 4, 5, 6, 7]}, - {"value": "1-7", "text": "1-7", "days": [1, 2, 3, 4, 5, 6, 7]}, - {"value": "R8-11", "text": "R8-11", "days": [1, 2, 3, 4, 5, 6, 7]}, - { - "value": "12-17-HARD", - "text": "12-17-HARD", - "days": [1, 2, 3, 4, 5, 6, 7], - }, - {"value": "CE-6", "text": "龙门币-6/5", "days": [2, 4, 6, 7]}, - {"value": "AP-5", "text": "红票-5", "days": [1, 4, 6, 7]}, - {"value": "CA-5", "text": "技能-5", "days": [2, 3, 5, 7]}, - {"value": "LS-6", "text": "经验-6/5", "days": [1, 2, 3, 4, 5, 6, 7]}, - {"value": "SK-5", "text": "碳-5", "days": [1, 3, 5, 6]}, - {"value": "PR-A-1", "text": "奶/盾芯片", "days": [1, 4, 5, 7]}, - {"value": "PR-A-2", "text": "奶/盾芯片组", "days": [1, 4, 5, 7]}, - {"value": "PR-B-1", "text": "术/狙芯片", "days": [1, 2, 5, 6]}, - {"value": "PR-B-2", "text": "术/狙芯片组", "days": [1, 2, 5, 6]}, - {"value": "PR-C-1", "text": "先/辅芯片", "days": [3, 4, 6, 7]}, - {"value": "PR-C-2", "text": "先/辅芯片组", "days": [3, 4, 6, 7]}, - {"value": "PR-D-1", "text": "近/特芯片", "days": [2, 3, 6, 7]}, - {"value": "PR-D-2", "text": "近/特芯片组", "days": [2, 3, 6, 7]}, - ] + for day in range(0, 8): - for gameid_info in gameid_list: - if day in gameid_info["days"]: - gameid_dict["value"].append(gameid_info["value"]) - gameid_dict["text"].append(gameid_info["text"]) + today_gameid_dict = {"value": [], "text": []} - self.gameid_dict[calendar.day_name[day - 1]] = gameid_dict + for gameid_info in gameid_daily_info: + + if day in gameid_info["days"] or day == 0: + today_gameid_dict["value"].append(gameid_info["value"]) + today_gameid_dict["text"].append(gameid_info["text"]) + + self.gameid_dict[calendar.day_name[day - 1] if day > 0 else "ALL"] = { + "value": today_gameid_dict["value"] + ss_gameid_dict["value"], + "text": today_gameid_dict["text"] + ss_gameid_dict["text"], + } self.gameid_refreshed.emit() diff --git a/app/models/MAA.py b/app/models/MAA.py index 5b1ceef..edbef87 100644 --- a/app/models/MAA.py +++ b/app/models/MAA.py @@ -102,6 +102,9 @@ class MaaManager(QObject): "Path": info["Path"], "Config": info["Config"].toDict(), } + planed_info = info["Config"].get_plan_info() + for key, value in planed_info.items(): + self.data[name]["Config"]["Info"][key] = value self.data = dict(sorted(self.data.items(), key=lambda x: int(x[0][3:]))) diff --git a/app/services/notification.py b/app/services/notification.py index 4cb60bb..7d17545 100644 --- a/app/services/notification.py +++ b/app/services/notification.py @@ -254,7 +254,7 @@ class Notification(QWidget): self.push_info_bar.emit( "error", "企业微信群机器人通知推送失败", - f'使用企业微信群机器人推送通知时出错:{info["errmsg"]}', + f"使用企业微信群机器人推送通知时出错:{err}", -1, ) return None @@ -267,10 +267,10 @@ class Notification(QWidget): self.push_info_bar.emit( "error", "企业微信群机器人通知推送失败", - f'使用企业微信群机器人推送通知时出错:{info["errmsg"]}', + f"使用企业微信群机器人推送通知时出错:{err}", -1, ) - return f'使用企业微信群机器人推送通知时出错:{info["errmsg"]}' + return f"使用企业微信群机器人推送通知时出错:{err}" def send_test_notification(self): """发送测试通知到所有已启用的通知渠道""" diff --git a/app/ui/Widget.py b/app/ui/Widget.py index ea5f8d0..db85a2d 100644 --- a/app/ui/Widget.py +++ b/app/ui/Widget.py @@ -477,7 +477,7 @@ class LineEditSettingCard(SettingCard): def __textChanged(self, content: str): - self.configItem.valueChanged.disconnect() + self.configItem.valueChanged.disconnect(self.setValue) self.qconfig.set(self.configItem, content.strip()) self.configItem.valueChanged.connect(self.setValue) @@ -485,7 +485,7 @@ class LineEditSettingCard(SettingCard): def setValue(self, content: str): - self.LineEdit.textChanged.disconnect() + self.LineEdit.textChanged.disconnect(self.__textChanged) self.LineEdit.setText(content.strip()) self.LineEdit.textChanged.connect(self.__textChanged) @@ -527,7 +527,7 @@ class PasswordLineEditSettingCard(SettingCard): def __textChanged(self, content: str): - self.configItem.valueChanged.disconnect() + self.configItem.valueChanged.disconnect(self.setValue) if self.algorithm == "DPAPI": self.qconfig.set(self.configItem, Crypto.win_encryptor(content)) elif self.algorithm == "AUTO": @@ -538,7 +538,7 @@ class PasswordLineEditSettingCard(SettingCard): def setValue(self, content: str): - self.LineEdit.textChanged.disconnect() + self.LineEdit.textChanged.disconnect(self.__textChanged) if self.algorithm == "DPAPI": self.LineEdit.setText(Crypto.win_decryptor(content)) elif self.algorithm == "AUTO": @@ -756,7 +756,7 @@ class NoOptionComboBoxSettingCard(SettingCard): value: List[str], texts: List[str], qconfig: QConfig, - configItem: OptionsConfigItem, + configItem: ConfigItem, parent=None, ): @@ -789,7 +789,7 @@ class NoOptionComboBoxSettingCard(SettingCard): def reLoadOptions(self, value: List[str], texts: List[str]): - self.comboBox.currentIndexChanged.disconnect() + self.comboBox.currentIndexChanged.disconnect(self._onCurrentIndexChanged) self.comboBox.clear() self.optionToText = {o: t for o, t in zip(value, texts)} for text, option in zip(texts, value): @@ -811,7 +811,7 @@ class EditableComboBoxSettingCard(SettingCard): value: List[str], texts: List[str], qconfig: QConfig, - configItem: OptionsConfigItem, + configItem: ConfigItem, parent=None, ): @@ -861,7 +861,7 @@ class EditableComboBoxSettingCard(SettingCard): def reLoadOptions(self, value: List[str], texts: List[str]): - self.comboBox.currentIndexChanged.disconnect() + self.comboBox.currentIndexChanged.disconnect(self._onCurrentIndexChanged) self.comboBox.clear() self.optionToText = {o: t for o, t in zip(value, texts)} for text, option in zip(texts, value): @@ -899,6 +899,169 @@ class EditableComboBoxSettingCard(SettingCard): self.currentIndexChanged.emit(self.count() - 1) +class SpinBoxWithPlanSettingCard(SpinBoxSettingCard): + + textChanged = Signal(int) + + def __init__( + self, + icon: Union[str, QIcon, FluentIconBase], + title: str, + content: Union[str, None], + range: tuple[int, int], + qconfig: QConfig, + configItem: ConfigItem, + parent=None, + ): + + super().__init__(icon, title, content, range, qconfig, configItem, parent) + + self.configItem_plan = None + + self.LineEdit = LineEdit(self) + self.LineEdit.setMinimumWidth(150) + self.LineEdit.setReadOnly(True) + self.LineEdit.setVisible(False) + + self.hBoxLayout.insertWidget(5, self.LineEdit, 0, Qt.AlignRight) + + def setText(self, value: int) -> None: + self.LineEdit.setText(str(value)) + + def switch_mode(self, mode: str) -> None: + """切换模式""" + + if mode == "固定": + + self.LineEdit.setVisible(False) + self.SpinBox.setVisible(True) + + elif mode == "计划": + + self.SpinBox.setVisible(False) + self.LineEdit.setVisible(True) + + def change_plan(self, configItem_plan: ConfigItem) -> None: + """切换计划""" + + if self.configItem_plan is not None: + self.configItem_plan.valueChanged.disconnect(self.setText) + self.configItem_plan = configItem_plan + self.configItem_plan.valueChanged.connect(self.setText) + self.setText(self.qconfig.get(self.configItem_plan)) + + +class ComboBoxWithPlanSettingCard(ComboBoxSettingCard): + + def __init__( + self, + icon: Union[str, QIcon, FluentIconBase], + title: str, + content: Union[str, None], + texts: List[str], + qconfig: QConfig, + configItem: OptionsConfigItem, + parent=None, + ): + + super().__init__(icon, title, content, texts, qconfig, configItem, parent) + + self.configItem_plan = None + + self.LineEdit = LineEdit(self) + self.LineEdit.setMinimumWidth(150) + self.LineEdit.setReadOnly(True) + self.LineEdit.setVisible(False) + + self.hBoxLayout.insertWidget(5, self.LineEdit, 0, Qt.AlignRight) + + def setText(self, value: str) -> None: + + if value not in self.optionToText: + self.optionToText[value] = value + + self.LineEdit.setText(self.optionToText[value]) + + def switch_mode(self, mode: str) -> None: + """切换模式""" + + if mode == "固定": + + self.LineEdit.setVisible(False) + self.comboBox.setVisible(True) + + elif mode == "计划": + + self.comboBox.setVisible(False) + self.LineEdit.setVisible(True) + + def change_plan(self, configItem_plan: ConfigItem) -> None: + """切换计划""" + + if self.configItem_plan is not None: + self.configItem_plan.valueChanged.disconnect(self.setText) + self.configItem_plan = configItem_plan + self.configItem_plan.valueChanged.connect(self.setText) + self.setText(self.qconfig.get(self.configItem_plan)) + + +class EditableComboBoxWithPlanSettingCard(EditableComboBoxSettingCard): + + def __init__( + self, + icon: Union[str, QIcon, FluentIconBase], + title: str, + content: Union[str, None], + value: List[str], + texts: List[str], + qconfig: QConfig, + configItem: ConfigItem, + parent=None, + ): + + super().__init__( + icon, title, content, value, texts, qconfig, configItem, parent + ) + + self.configItem_plan = None + + self.LineEdit = LineEdit(self) + self.LineEdit.setMinimumWidth(150) + self.LineEdit.setReadOnly(True) + self.LineEdit.setVisible(False) + + self.hBoxLayout.insertWidget(5, self.LineEdit, 0, Qt.AlignRight) + + def setText(self, value: str) -> None: + + if value not in self.optionToText: + self.optionToText[value] = value + + self.LineEdit.setText(self.optionToText[value]) + + def switch_mode(self, mode: str) -> None: + """切换模式""" + + if mode == "固定": + + self.LineEdit.setVisible(False) + self.comboBox.setVisible(True) + + elif mode == "计划": + + self.comboBox.setVisible(False) + self.LineEdit.setVisible(True) + + def change_plan(self, configItem_plan: ConfigItem) -> None: + """切换计划""" + + if self.configItem_plan is not None: + self.configItem_plan.valueChanged.disconnect(self.setText) + self.configItem_plan = configItem_plan + self.configItem_plan.valueChanged.connect(self.setText) + self.setText(self.qconfig.get(self.configItem_plan)) + + class TimeEditSettingCard(SettingCard): enabledChanged = Signal(bool) @@ -1154,7 +1317,7 @@ class NoOptionComboBoxSetting(ComboBox): def reLoadOptions(self, value: List[str], texts: List[str]): - self.currentIndexChanged.disconnect() + self.currentIndexChanged.disconnect(self._onCurrentIndexChanged) self.clear() self.optionToText = {o: t for o, t in zip(value, texts)} for text, option in zip(texts, value): @@ -1210,7 +1373,7 @@ class EditableComboBoxSetting(EditableComboBox): def reLoadOptions(self, value: List[str], texts: List[str]): - self.currentIndexChanged.disconnect() + self.currentIndexChanged.disconnect(self._onCurrentIndexChanged) self.clear() self.optionToText = {o: t for o, t in zip(value, texts)} for text, option in zip(texts, value): diff --git a/app/ui/main_window.py b/app/ui/main_window.py index 9fc9a69..76aac32 100644 --- a/app/ui/main_window.py +++ b/app/ui/main_window.py @@ -81,8 +81,8 @@ class AUTO_MAA(MSFluentWindow): # 创建主窗口 self.home = Home(self) - self.member_manager = MemberManager(self) self.plan_manager = PlanManager(self) + self.member_manager = MemberManager(self) self.queue_manager = QueueManager(self) self.dispatch_center = DispatchCenter(self) self.history = History(self) @@ -137,23 +137,7 @@ class AUTO_MAA(MSFluentWindow): FluentIcon.SETTING, NavigationItemPosition.BOTTOM, ) - self.stackedWidget.currentChanged.connect( - lambda index: ( - self.queue_manager.reload_member_name() if index == 2 else None - ) - ) - self.stackedWidget.currentChanged.connect( - lambda index: ( - self.dispatch_center.pivot.setCurrentItem("主调度台") - if index == 3 - else None - ) - ) - self.stackedWidget.currentChanged.connect( - lambda index: ( - self.dispatch_center.update_top_bar() if index == 3 else None - ) - ) + self.stackedWidget.currentChanged.connect(self.__currentChanged) # 创建系统托盘及其菜单 self.tray = QSystemTrayIcon( @@ -250,43 +234,6 @@ class AUTO_MAA(MSFluentWindow): else: self.setStyleSheet("background-color: #ffffff;") - def start_up_task(self) -> None: - """启动时任务""" - - # 清理旧日志 - self.clean_old_logs() - - # 清理安装包 - if (Config.app_path / "AUTO_MAA-Setup.exe").exists(): - try: - (Config.app_path / "AUTO_MAA-Setup.exe").unlink() - except Exception: - pass - - # 检查密码 - self.setting.check_PASSWORD() - - # 获取主题图像 - if Config.get(Config.function_HomeImageMode) == "主题图像": - self.home.get_home_image() - - # 直接运行主任务 - if Config.get(Config.start_IfRunDirectly): - - self.start_main_task() - - # 获取公告 - self.setting.show_notice(if_first=True) - - # 检查更新 - if Config.get(Config.update_IfAutoUpdate): - self.setting.check_update(if_first=True) - - # 直接最小化 - if Config.get(Config.start_IfMinimizeDirectly): - - self.titleBar.minBtn.click() - def set_min_method(self) -> None: """设置最小化方法""" @@ -305,61 +252,6 @@ class AUTO_MAA(MSFluentWindow): if reason == QSystemTrayIcon.DoubleClick: self.show_ui("显示主窗口") - def clean_old_logs(self): - """ - 删除超过用户设定天数的日志文件(基于目录日期) - """ - - if Config.get(Config.function_HistoryRetentionTime) == 0: - logger.info("由于用户设置日志永久保留,跳过日志清理") - return - - deleted_count = 0 - - for date_folder in (Config.app_path / "history").iterdir(): - if not date_folder.is_dir(): - continue # 只处理日期文件夹 - - try: - # 只检查 `YYYY-MM-DD` 格式的文件夹 - folder_date = datetime.strptime(date_folder.name, "%Y-%m-%d") - if datetime.now() - folder_date > timedelta( - days=Config.get(Config.function_HistoryRetentionTime) - ): - shutil.rmtree(date_folder, ignore_errors=True) - deleted_count += 1 - logger.info(f"已删除超期日志目录: {date_folder}") - except ValueError: - logger.warning(f"非日期格式的目录: {date_folder}") - - logger.info(f"清理完成: {deleted_count} 个日期目录") - - def start_main_task(self) -> None: - """启动主任务""" - - if "调度队列_1" in Config.queue_dict: - - logger.info("自动添加任务:调度队列_1") - TaskManager.add_task( - "自动代理_主调度台", - "调度队列_1", - Config.queue_dict["调度队列_1"]["Config"].toDict(), - ) - - elif "脚本_1" in Config.member_dict: - - logger.info("自动添加任务:脚本_1") - TaskManager.add_task( - "自动代理_主调度台", "自定义队列", {"Queue": {"Member_1": "脚本_1"}} - ) - - else: - - logger.warning("启动主任务失败:未找到有效的主任务配置文件") - MainInfoBar.push_info_bar( - "warning", "启动主任务失败", "“调度队列_1”与“脚本_1”均不存在", -1 - ) - def show_ui( self, mode: str, if_quick: bool = False, if_start: bool = False ) -> None: @@ -440,6 +332,109 @@ class AUTO_MAA(MSFluentWindow): self.window().hide() self.tray.show() + def start_up_task(self) -> None: + """启动时任务""" + + # 清理旧日志 + self.clean_old_logs() + + # 清理安装包 + if (Config.app_path / "AUTO_MAA-Setup.exe").exists(): + try: + (Config.app_path / "AUTO_MAA-Setup.exe").unlink() + except Exception: + pass + + # 检查密码 + self.setting.check_PASSWORD() + + # 获取主题图像 + if Config.get(Config.function_HomeImageMode) == "主题图像": + self.home.get_home_image() + + # 直接运行主任务 + if Config.get(Config.start_IfRunDirectly): + + self.start_main_task() + + # 获取公告 + self.setting.show_notice(if_first=True) + + # 检查更新 + if Config.get(Config.update_IfAutoUpdate): + self.setting.check_update(if_first=True) + + # 直接最小化 + if Config.get(Config.start_IfMinimizeDirectly): + + self.titleBar.minBtn.click() + + def clean_old_logs(self): + """ + 删除超过用户设定天数的日志文件(基于目录日期) + """ + + if Config.get(Config.function_HistoryRetentionTime) == 0: + logger.info("由于用户设置日志永久保留,跳过日志清理") + return + + deleted_count = 0 + + for date_folder in (Config.app_path / "history").iterdir(): + if not date_folder.is_dir(): + continue # 只处理日期文件夹 + + try: + # 只检查 `YYYY-MM-DD` 格式的文件夹 + folder_date = datetime.strptime(date_folder.name, "%Y-%m-%d") + if datetime.now() - folder_date > timedelta( + days=Config.get(Config.function_HistoryRetentionTime) + ): + shutil.rmtree(date_folder, ignore_errors=True) + deleted_count += 1 + logger.info(f"已删除超期日志目录: {date_folder}") + except ValueError: + logger.warning(f"非日期格式的目录: {date_folder}") + + logger.info(f"清理完成: {deleted_count} 个日期目录") + + def start_main_task(self) -> None: + """启动主任务""" + + if "调度队列_1" in Config.queue_dict: + + logger.info("自动添加任务:调度队列_1") + TaskManager.add_task( + "自动代理_主调度台", + "调度队列_1", + Config.queue_dict["调度队列_1"]["Config"].toDict(), + ) + + elif "脚本_1" in Config.member_dict: + + logger.info("自动添加任务:脚本_1") + TaskManager.add_task( + "自动代理_主调度台", "自定义队列", {"Queue": {"Member_1": "脚本_1"}} + ) + + else: + + logger.warning("启动主任务失败:未找到有效的主任务配置文件") + MainInfoBar.push_info_bar( + "warning", "启动主任务失败", "“调度队列_1”与“脚本_1”均不存在", -1 + ) + + def __currentChanged(self, index: int) -> None: + """切换界面时任务""" + + if index == 1: + self.member_manager.reload_plan_name() + elif index == 3: + self.queue_manager.reload_member_name() + elif index == 4: + self.dispatch_center.pivot.setCurrentItem("主调度台") + self.dispatch_center.update_top_bar() + def closeEvent(self, event: QCloseEvent): """清理残余进程""" diff --git a/app/ui/member_manager.py b/app/ui/member_manager.py index cf4e1d6..6adeead 100644 --- a/app/ui/member_manager.py +++ b/app/ui/member_manager.py @@ -67,7 +67,10 @@ from .Widget import ( SpinBoxSettingCard, ComboBoxMessageBox, SettingFlyoutView, - EditableComboBoxSettingCard, + NoOptionComboBoxSettingCard, + ComboBoxWithPlanSettingCard, + EditableComboBoxWithPlanSettingCard, + SpinBoxWithPlanSettingCard, PasswordLineEditSettingCard, UserLableSettingCard, ComboBoxSettingCard, @@ -183,7 +186,7 @@ class MemberManager(QWidget): name = self.member_manager.pivot.currentRouteKey() - if name == None: + if name is None: logger.warning("删除脚本实例时未选择脚本实例") MainInfoBar.push_info_bar( "warning", "未选择脚本实例", "请选择一个脚本实例", 5000 @@ -223,7 +226,7 @@ class MemberManager(QWidget): name = self.member_manager.pivot.currentRouteKey() - if name == None: + if name is None: logger.warning("向左移动脚本实例时未选择脚本实例") MainInfoBar.push_info_bar( "warning", "未选择脚本实例", "请选择一个脚本实例", 5000 @@ -271,7 +274,7 @@ class MemberManager(QWidget): name = self.member_manager.pivot.currentRouteKey() - if name == None: + if name is None: logger.warning("向右移动脚本实例时未选择脚本实例") MainInfoBar.push_info_bar( "warning", "未选择脚本实例", "请选择一个脚本实例", 5000 @@ -472,11 +475,57 @@ class MemberManager(QWidget): self.key.setIcon(FluentIcon.HIDE) self.key.setChecked(False) + def reload_plan_name(self): + """刷新计划表名称""" + + plan_list = [ + ["固定"] + [_ for _ in Config.plan_dict.keys()], + ["固定"] + + [ + ( + k + if v["Config"].get(v["Config"].Info_Name) == "" + else f"{k} - {v["Config"].get(v["Config"].Info_Name)}" + ) + for k, v in Config.plan_dict.items() + ], + ] + for member in self.member_manager.script_list: + + if isinstance(member, MemberManager.MemberSettingBox.MaaSettingBox): + + for user_setting in member.user_setting.user_manager.script_list: + + user_setting.card_GameIdMode.comboBox.currentIndexChanged.disconnect( + user_setting.switch_gameid_mode + ) + user_setting.card_GameIdMode.reLoadOptions( + plan_list[0], plan_list[1] + ) + user_setting.card_GameIdMode.comboBox.currentIndexChanged.connect( + user_setting.switch_gameid_mode + ) + + self.refresh_plan_info() + def refresh_dashboard(self): """刷新所有脚本实例的用户仪表盘""" - for script in self.member_manager.script_list: - script.user_setting.user_manager.user_dashboard.load_info() + for member in self.member_manager.script_list: + + if isinstance(member, MemberManager.MemberSettingBox.MaaSettingBox): + member.user_setting.user_manager.user_dashboard.load_info() + + def refresh_plan_info(self): + """刷新所有计划信息""" + + for member in self.member_manager.script_list: + + if isinstance(member, MemberManager.MemberSettingBox.MaaSettingBox): + + member.user_setting.user_manager.user_dashboard.load_info() + for user_setting in member.user_setting.user_manager.script_list: + user_setting.switch_gameid_mode() class MemberSettingBox(QWidget): """脚本管理子页面组""" @@ -841,7 +890,7 @@ class MemberManager(QWidget): name = self.user_manager.pivot.currentRouteKey() - if name == None: + if name is None: logger.warning("未选择用户") MainInfoBar.push_info_bar( "warning", "未选择用户", "请先选择一个用户", 5000 @@ -900,7 +949,7 @@ class MemberManager(QWidget): name = self.user_manager.pivot.currentRouteKey() - if name == None: + if name is None: logger.warning("未选择用户") MainInfoBar.push_info_bar( "warning", "未选择用户", "请先选择一个用户", 5000 @@ -959,7 +1008,7 @@ class MemberManager(QWidget): name = self.user_manager.pivot.currentRouteKey() - if name == None: + if name is None: logger.warning("未选择用户") MainInfoBar.push_info_bar( "warning", "未选择用户", "请先选择一个用户", 5000 @@ -1195,6 +1244,8 @@ class MemberManager(QWidget): else "本周剿灭未完成" ) + gameid_info = config.get_plan_info() + button = PrimaryToolButton( FluentIcon.CHEVRON_RIGHT, self ) @@ -1243,9 +1294,7 @@ class MemberManager(QWidget): self.dashboard.setItem( int(name[3:]) - 1, 5, - QTableWidgetItem( - str(config.get(config.Info_MedicineNumb)) - ), + QTableWidgetItem(str(gameid_info["MedicineNumb"])), ) self.dashboard.setItem( int(name[3:]) - 1, @@ -1253,12 +1302,12 @@ class MemberManager(QWidget): QTableWidgetItem( Config.gameid_dict["ALL"]["text"][ Config.gameid_dict["ALL"]["value"].index( - config.get(config.Info_GameId) + gameid_info["GameId"] ) ] - if config.get(config.Info_GameId) + if gameid_info["GameId"] in Config.gameid_dict["ALL"]["value"] - else config.get(config.Info_GameId) + else gameid_info["GameId"] ), ) self.dashboard.setItem( @@ -1267,12 +1316,12 @@ class MemberManager(QWidget): QTableWidgetItem( Config.gameid_dict["ALL"]["text"][ Config.gameid_dict["ALL"]["value"].index( - config.get(config.Info_GameId_1) + gameid_info["GameId_1"] ) ] - if config.get(config.Info_GameId_1) + if gameid_info["GameId_1"] in Config.gameid_dict["ALL"]["value"] - else config.get(config.Info_GameId_1) + else gameid_info["GameId_1"] ), ) self.dashboard.setItem( @@ -1281,12 +1330,12 @@ class MemberManager(QWidget): QTableWidgetItem( Config.gameid_dict["ALL"]["text"][ Config.gameid_dict["ALL"]["value"].index( - config.get(config.Info_GameId_2) + gameid_info["GameId_2"] ) ] - if config.get(config.Info_GameId_2) + if gameid_info["GameId_2"] in Config.gameid_dict["ALL"]["value"] - else config.get(config.Info_GameId_2) + else gameid_info["GameId_2"] ), ) self.dashboard.setItem( @@ -1294,22 +1343,20 @@ class MemberManager(QWidget): 9, QTableWidgetItem( "不使用" - if config.get(config.Info_GameId_Remain) == "-" + if gameid_info["GameId_Remain"] == "-" else ( ( Config.gameid_dict["ALL"]["text"][ Config.gameid_dict["ALL"][ "value" ].index( - config.get( - config.Info_GameId_Remain - ) + gameid_info["GameId_Remain"] ) ] ) - if config.get(config.Info_GameId_Remain) + if gameid_info["GameId_Remain"] in Config.gameid_dict["ALL"]["value"] - else config.get(config.Info_GameId_Remain) + else gameid_info["GameId_Remain"] ) ), ) @@ -1333,6 +1380,19 @@ class MemberManager(QWidget): f"用户_{uid}" ]["Path"] + plan_list = [ + ["固定"] + [_ for _ in Config.plan_dict.keys()], + ["固定"] + + [ + ( + k + if v["Config"].get(v["Config"].Info_Name) == "" + else f"{k} - {v["Config"].get(v["Config"].Info_Name)}" + ) + for k, v in Config.plan_dict.items() + ], + ] + self.card_Name = LineEditSettingCard( icon=FluentIcon.PEOPLE, title="用户名", @@ -1360,15 +1420,17 @@ class MemberManager(QWidget): configItem=self.config.Info_Mode, parent=self, ) - self.card_GameIdMode = ComboBoxSettingCard( + self.card_GameIdMode = NoOptionComboBoxSettingCard( icon=FluentIcon.DICTIONARY, title="关卡配置模式", content="刷理智关卡号的配置模式", - texts=["固定"], + value=plan_list[0], + texts=plan_list[1], qconfig=self.config, configItem=self.config.Info_GameIdMode, parent=self, ) + self.card_GameIdMode.comboBox.setMinimumWidth(0) self.card_Server = ComboBoxSettingCard( icon=FluentIcon.PROJECTOR, title="服务器", @@ -1446,7 +1508,7 @@ class MemberManager(QWidget): configItem=self.config.Info_Notes, parent=self, ) - self.card_MedicineNumb = SpinBoxSettingCard( + self.card_MedicineNumb = SpinBoxWithPlanSettingCard( icon=FluentIcon.GAME, title="吃理智药", content="吃理智药次数,输入0以关闭", @@ -1455,7 +1517,7 @@ class MemberManager(QWidget): configItem=self.config.Info_MedicineNumb, parent=self, ) - self.card_SeriesNumb = ComboBoxSettingCard( + self.card_SeriesNumb = ComboBoxWithPlanSettingCard( icon=FluentIcon.GAME, title="连战次数", content="连战次数较大时建议搭配剩余理智关卡使用", @@ -1465,7 +1527,7 @@ class MemberManager(QWidget): parent=self, ) self.card_SeriesNumb.comboBox.setMinimumWidth(150) - self.card_GameId = EditableComboBoxSettingCard( + self.card_GameId = EditableComboBoxWithPlanSettingCard( icon=FluentIcon.GAME, title="关卡选择", content="按下回车以添加自定义关卡号", @@ -1475,7 +1537,7 @@ class MemberManager(QWidget): configItem=self.config.Info_GameId, parent=self, ) - self.card_GameId_1 = EditableComboBoxSettingCard( + self.card_GameId_1 = EditableComboBoxWithPlanSettingCard( icon=FluentIcon.GAME, title="备选关卡 - 1", content="按下回车以添加自定义关卡号", @@ -1485,7 +1547,7 @@ class MemberManager(QWidget): configItem=self.config.Info_GameId_1, parent=self, ) - self.card_GameId_2 = EditableComboBoxSettingCard( + self.card_GameId_2 = EditableComboBoxWithPlanSettingCard( icon=FluentIcon.GAME, title="备选关卡 - 2", content="按下回车以添加自定义关卡号", @@ -1495,18 +1557,20 @@ class MemberManager(QWidget): configItem=self.config.Info_GameId_2, parent=self, ) - self.card_GameId_Remain = EditableComboBoxSettingCard( - icon=FluentIcon.GAME, - title="剩余理智关卡", - content="按下回车以添加自定义关卡号", - value=Config.gameid_dict["ALL"]["value"], - texts=[ - "不使用" if _ == "当前/上次" else _ - for _ in Config.gameid_dict["ALL"]["text"] - ], - qconfig=self.config, - configItem=self.config.Info_GameId_Remain, - parent=self, + self.card_GameId_Remain = ( + EditableComboBoxWithPlanSettingCard( + icon=FluentIcon.GAME, + title="剩余理智关卡", + content="按下回车以添加自定义关卡号", + value=Config.gameid_dict["ALL"]["value"], + texts=[ + "不使用" if _ == "当前/上次" else _ + for _ in Config.gameid_dict["ALL"]["text"] + ], + qconfig=self.config, + configItem=self.config.Info_GameId_Remain, + parent=self, + ) ) self.card_UserLable = UserLableSettingCard( @@ -1624,10 +1688,14 @@ class MemberManager(QWidget): self.set_infrastructure ) self.card_NotifySet.clicked.connect(self.set_notify) + self.card_GameIdMode.comboBox.currentIndexChanged.connect( + self.switch_gameid_mode + ) Config.gameid_refreshed.connect(self.refresh_gameid) Config.PASSWORD_refreshed.connect(self.refresh_password) self.switch_mode() + self.switch_gameid_mode() self.switch_infrastructure() def switch_mode(self) -> None: @@ -1646,6 +1714,40 @@ class MemberManager(QWidget): self.card_Annihilation.button.setVisible(True) self.card_Routine.setVisible(True) + def switch_gameid_mode(self) -> None: + + for card, name in zip( + [ + self.card_MedicineNumb, + self.card_SeriesNumb, + self.card_GameId, + self.card_GameId_1, + self.card_GameId_2, + self.card_GameId_Remain, + ], + [ + "MedicineNumb", + "SeriesNumb", + "GameId", + "GameId_1", + "GameId_2", + "GameId_Remain", + ], + ): + + card.switch_mode( + self.config.get(self.config.Info_GameIdMode)[:2] + ) + if ( + self.config.get(self.config.Info_GameIdMode) + != "固定" + ): + card.change_plan( + Config.plan_dict[ + self.config.get(self.config.Info_GameIdMode) + ]["Config"].get_current_info(name) + ) + def switch_infrastructure(self) -> None: if ( diff --git a/app/ui/plan_manager.py b/app/ui/plan_manager.py index f236b88..f96cad3 100644 --- a/app/ui/plan_manager.py +++ b/app/ui/plan_manager.py @@ -40,13 +40,14 @@ from qfluentwidgets import ( CommandBar, TableWidget, ) -from typing import List +from typing import List, Dict, Union import shutil from app.core import Config, MainInfoBar, MaaPlanConfig -from app.services import Crypto from .Widget import ( ComboBoxMessageBox, + LineEditSettingCard, + ComboBoxSettingCard, SpinBoxSetting, EditableComboBoxSetting, ComboBoxSetting, @@ -134,7 +135,7 @@ class PlanManager(QWidget): name = self.plan_manager.pivot.currentRouteKey() - if name == None: + if name is None: logger.warning("删除计划表时未选择计划表") MainInfoBar.push_info_bar( "warning", "未选择计划表", "请选择一个计划表", 5000 @@ -172,7 +173,7 @@ class PlanManager(QWidget): name = self.plan_manager.pivot.currentRouteKey() - if name == None: + if name is None: logger.warning("向左移动计划表时未选择计划表") MainInfoBar.push_info_bar( "warning", "未选择计划表", "请选择一个计划表", 5000 @@ -220,7 +221,7 @@ class PlanManager(QWidget): name = self.plan_manager.pivot.currentRouteKey() - if name == None: + if name is None: logger.warning("向右移动计划表时未选择计划表") MainInfoBar.push_info_bar( "warning", "未选择计划表", "请选择一个计划表", 5000 @@ -321,6 +322,7 @@ class PlanManager(QWidget): """清空所有子界面""" for sub_interface in self.script_list: + Config.gameid_refreshed.disconnect(sub_interface.refresh_gameid) self.stackedWidget.removeWidget(sub_interface) sub_interface.deleteLater() self.script_list.clear() @@ -344,15 +346,35 @@ class PlanManager(QWidget): super().__init__(parent) self.setObjectName(f"计划_{uid}") + self.setTitle("MAA计划表") self.config = Config.plan_dict[f"计划_{uid}"]["Config"] - self.dashboard = TableWidget(self) - self.dashboard.setColumnCount(8) - self.dashboard.setRowCount(6) - self.dashboard.setHorizontalHeaderLabels( + self.card_Name = LineEditSettingCard( + icon=FluentIcon.EDIT, + title="计划表名称", + content="用于标识计划表的名称", + text="请输入计划表名称", + qconfig=self.config, + configItem=self.config.Info_Name, + parent=self, + ) + self.card_Mode = ComboBoxSettingCard( + icon=FluentIcon.DICTIONARY, + title="计划模式", + content="全局模式下计划内容固定,周计划模式下计划按周一到周日切换", + texts=["全局", "周计划"], + qconfig=self.config, + configItem=self.config.Info_Mode, + parent=self, + ) + + self.table = TableWidget(self) + self.table.setColumnCount(8) + self.table.setRowCount(6) + self.table.setHorizontalHeaderLabels( ["全局", "周一", "周二", "周三", "周四", "周五", "周六", "周日"] ) - self.dashboard.setVerticalHeaderLabels( + self.table.setVerticalHeaderLabels( [ "吃理智药", "连战次数", @@ -362,37 +384,60 @@ class PlanManager(QWidget): "剩余理智", ] ) - self.dashboard.setEditTriggers(TableWidget.NoEditTriggers) + self.table.setAlternatingRowColors(False) + self.table.setEditTriggers(TableWidget.NoEditTriggers) for col in range(8): - self.dashboard.horizontalHeader().setSectionResizeMode( + self.table.horizontalHeader().setSectionResizeMode( col, QHeaderView.ResizeMode.Stretch ) + for row in range(6): + self.table.verticalHeader().setSectionResizeMode( + row, QHeaderView.ResizeMode.ResizeToContents + ) - self.viewLayout.addWidget(self.dashboard) - self.viewLayout.setContentsMargins(3, 0, 3, 3) + self.item_dict: Dict[ + str, + Dict[ + str, + Union[SpinBoxSetting, ComboBoxSetting, EditableComboBoxSetting], + ], + ] = {} for col, (group, name_dict) in enumerate( self.config.config_item_dict.items() ): + self.item_dict[group] = {} + for row, (name, configItem) in enumerate(name_dict.items()): if name == "MedicineNumb": - setting_item = SpinBoxSetting( + self.item_dict[group][name] = SpinBoxSetting( range=(0, 1024), qconfig=self.config, configItem=configItem, parent=self, ) elif name == "SeriesNumb": - setting_item = ComboBoxSetting( + self.item_dict[group][name] = ComboBoxSetting( texts=["AUTO", "6", "5", "4", "3", "2", "1", "不选择"], qconfig=self.config, configItem=configItem, parent=self, ) + elif name == "GameId_Remain": + self.item_dict[group][name] = EditableComboBoxSetting( + value=Config.gameid_dict[group]["value"], + texts=[ + "不使用" if _ == "当前/上次" else _ + for _ in Config.gameid_dict[group]["text"] + ], + qconfig=self.config, + configItem=configItem, + parent=self, + ) elif "GameId" in name: - setting_item = EditableComboBoxSetting( + self.item_dict[group][name] = EditableComboBoxSetting( value=Config.gameid_dict[group]["value"], texts=Config.gameid_dict[group]["text"], qconfig=self.config, @@ -400,4 +445,51 @@ class PlanManager(QWidget): parent=self, ) - self.dashboard.setCellWidget(row, col, setting_item) + self.table.setCellWidget(row, col, self.item_dict[group][name]) + + Layout = QVBoxLayout() + Layout.addWidget(self.card_Name) + Layout.addWidget(self.card_Mode) + Layout.addWidget(self.table) + + self.viewLayout.addLayout(Layout) + self.viewLayout.setSpacing(3) + self.viewLayout.setContentsMargins(3, 0, 3, 3) + + self.card_Mode.comboBox.currentIndexChanged.connect(self.switch_mode) + Config.gameid_refreshed.connect(self.refresh_gameid) + + self.switch_mode() + + def switch_mode(self) -> None: + """切换计划模式""" + + for group, name_dict in self.item_dict.items(): + for name, setting_item in name_dict.items(): + setting_item.setEnabled( + (group == "ALL") + == (self.config.get(self.config.Info_Mode) == "ALL") + ) + + def refresh_gameid(self): + + for group, name_dict in self.item_dict.items(): + + for name, setting_item in name_dict.items(): + + if name == "GameId_Remain": + + setting_item.reLoadOptions( + Config.gameid_dict[group]["value"], + [ + "不使用" if _ == "当前/上次" else _ + for _ in Config.gameid_dict[group]["text"] + ], + ) + + elif "GameId" in name: + + setting_item.reLoadOptions( + Config.gameid_dict[group]["value"], + Config.gameid_dict[group]["text"], + ) diff --git a/app/ui/queue_manager.py b/app/ui/queue_manager.py index 5120167..ee013b6 100644 --- a/app/ui/queue_manager.py +++ b/app/ui/queue_manager.py @@ -122,7 +122,7 @@ class QueueManager(QWidget): name = self.queue_manager.pivot.currentRouteKey() - if name == None: + if name is None: logger.warning("未选择调度队列") MainInfoBar.push_info_bar( "warning", "未选择调度队列", "请先选择一个调度队列", 5000 @@ -160,7 +160,7 @@ class QueueManager(QWidget): name = self.queue_manager.pivot.currentRouteKey() - if name == None: + if name is None: logger.warning("未选择调度队列") MainInfoBar.push_info_bar( "warning", "未选择调度队列", "请先选择一个调度队列", 5000 @@ -205,7 +205,7 @@ class QueueManager(QWidget): name = self.queue_manager.pivot.currentRouteKey() - if name == None: + if name is None: logger.warning("未选择调度队列") MainInfoBar.push_info_bar( "warning", "未选择调度队列", "请先选择一个调度队列", 5000 diff --git a/resources/version.json b/resources/version.json index 622187a..97ed255 100644 --- a/resources/version.json +++ b/resources/version.json @@ -4,7 +4,8 @@ "4.3.8.4": { "新增功能": [ "支持为每一个用户执行独立通知", - "输入文本框适配文本插入操作" + "输入文本框适配文本插入操作", + "计划表功能上线" ] }, "4.3.8.3": { @@ -23,7 +24,7 @@ "日志分析忽略MAA超时提示" ], "程序优化": [ - "配置类定义方法更新,预载入计划表相关配置" + "配置类定义方法更新" ] }, "4.3.8.1": {