feat(dialog): 实现对话框主题与拖拽功能
This commit is contained in:
444
app/task/MAA.py
444
app/task/MAA.py
@@ -176,9 +176,7 @@ class MaaManager:
|
||||
|
||||
# 开始代理
|
||||
for self.index, user in enumerate(self.user_list):
|
||||
|
||||
try:
|
||||
|
||||
self.cur_user_data = self.user_config[uuid.UUID(user["user_id"])]
|
||||
|
||||
if (self.script_config.get("Run", "ProxyTimesLimit") == 0) or (
|
||||
@@ -225,11 +223,9 @@ class MaaManager:
|
||||
if self.cur_user_data.get(
|
||||
"Info", "IfSkland"
|
||||
) and self.cur_user_data.get("Info", "SklandToken"):
|
||||
|
||||
if self.cur_user_data.get(
|
||||
"Data", "LastSklandDate"
|
||||
) != datetime.now().strftime("%Y-%m-%d"):
|
||||
|
||||
await Config.send_json(
|
||||
WebSocketMessage(
|
||||
id=self.ws_id,
|
||||
@@ -243,7 +239,6 @@ class MaaManager:
|
||||
)
|
||||
|
||||
for type, user_list in skland_result.items():
|
||||
|
||||
if type != "总计" and len(user_list) > 0:
|
||||
logger.info(
|
||||
f"用户: {user['user_id']} - 森空岛签到{type}: {'、'.join(user_list)}"
|
||||
@@ -299,7 +294,6 @@ class MaaManager:
|
||||
|
||||
# 剿灭-日常模式循环
|
||||
for mode in ["Annihilation", "Routine"]:
|
||||
|
||||
if self.run_book[mode]:
|
||||
continue
|
||||
|
||||
@@ -361,7 +355,6 @@ class MaaManager:
|
||||
|
||||
# 解析任务构成
|
||||
if mode == "Routine":
|
||||
|
||||
self.task_dict = {
|
||||
"WakeUp": str(
|
||||
self.cur_user_data.get("Task", "IfWakeUp")
|
||||
@@ -386,7 +379,6 @@ class MaaManager:
|
||||
}
|
||||
|
||||
elif mode == "Annihilation":
|
||||
|
||||
self.task_dict = {
|
||||
"WakeUp": "True",
|
||||
"Recruiting": "False",
|
||||
@@ -404,7 +396,6 @@ class MaaManager:
|
||||
|
||||
# 尝试次数循环
|
||||
for i in range(self.script_config.get("Run", "RunTimesLimit")):
|
||||
|
||||
if self.run_book[mode]:
|
||||
break
|
||||
|
||||
@@ -566,7 +557,6 @@ class MaaManager:
|
||||
|
||||
# 处理MAA结果
|
||||
if self.maa_result == "Success!":
|
||||
|
||||
# 标记任务完成
|
||||
self.run_book[mode] = True
|
||||
|
||||
@@ -743,7 +733,6 @@ class MaaManager:
|
||||
await self.result_record()
|
||||
|
||||
except Exception as e:
|
||||
|
||||
logger.exception(f"代理用户 {user['user_id']} 时出现异常: {e}")
|
||||
user["status"] = "异常"
|
||||
await Config.send_json(
|
||||
@@ -756,7 +745,6 @@ class MaaManager:
|
||||
|
||||
# 人工排查模式
|
||||
elif self.mode == "人工排查":
|
||||
|
||||
# 人工排查时, 屏蔽静默操作
|
||||
logger.info("人工排查任务开始, 屏蔽静默操作")
|
||||
Config.if_ignore_silence.append(self.script_id)
|
||||
@@ -766,7 +754,6 @@ class MaaManager:
|
||||
|
||||
# 开始排查
|
||||
for self.index, user in enumerate(self.user_list):
|
||||
|
||||
self.cur_user_data = self.user_config[uuid.UUID(user["user_id"])]
|
||||
|
||||
logger.info(f"开始排查用户: {user['user_id']}")
|
||||
@@ -787,7 +774,6 @@ class MaaManager:
|
||||
|
||||
# 启动重试循环
|
||||
while True:
|
||||
|
||||
# 配置MAA
|
||||
await self.set_maa("人工排查")
|
||||
|
||||
@@ -849,7 +835,6 @@ class MaaManager:
|
||||
break
|
||||
# 登录失败, 询问是否结束循环
|
||||
else:
|
||||
|
||||
uid = str(uuid.uuid4())
|
||||
await Config.send_json(
|
||||
WebSocketMessage(
|
||||
@@ -860,6 +845,7 @@ class MaaManager:
|
||||
"type": "Question",
|
||||
"title": "操作提示",
|
||||
"message": "MAA未能正确登录到PRTS, 是否重试?",
|
||||
"options": ["是", "否"],
|
||||
},
|
||||
).model_dump()
|
||||
)
|
||||
@@ -869,7 +855,6 @@ class MaaManager:
|
||||
|
||||
# 登录成功, 录入人工排查情况
|
||||
if self.run_book["SignIn"]:
|
||||
|
||||
uid = str(uuid.uuid4())
|
||||
await Config.send_json(
|
||||
WebSocketMessage(
|
||||
@@ -880,6 +865,7 @@ class MaaManager:
|
||||
"type": "Question",
|
||||
"title": "操作提示",
|
||||
"message": "请检查用户代理情况, 该用户是否正确完成代理任务?",
|
||||
"options": ["是", "否"],
|
||||
},
|
||||
).model_dump()
|
||||
)
|
||||
@@ -899,7 +885,6 @@ class MaaManager:
|
||||
|
||||
# 设置MAA模式
|
||||
elif self.mode == "设置脚本":
|
||||
|
||||
# 配置MAA
|
||||
await self.set_maa(self.mode)
|
||||
# 创建MAA任务
|
||||
@@ -982,7 +967,6 @@ class MaaManager:
|
||||
)
|
||||
|
||||
elif self.mode == "人工排查":
|
||||
|
||||
if self.run_book["SignIn"] and self.run_book["PassCheck"]:
|
||||
logger.info(
|
||||
f"用户 {self.user_list[self.index]['user_id']} 通过人工排查"
|
||||
@@ -1018,7 +1002,6 @@ class MaaManager:
|
||||
return self.check_result
|
||||
|
||||
if self.mode == "人工排查":
|
||||
|
||||
# 解除静默操作屏蔽
|
||||
logger.info("人工排查任务结束, 解除静默操作屏蔽")
|
||||
if self.script_id in Config.if_ignore_silence:
|
||||
@@ -1029,9 +1012,7 @@ class MaaManager:
|
||||
and hasattr(self, "index")
|
||||
and self.user_list[self.index]["status"] == "运行"
|
||||
):
|
||||
|
||||
if not self.maa_update_package:
|
||||
|
||||
self.maa_result = "用户手动中止任务"
|
||||
|
||||
# 保存运行日志以及统计信息
|
||||
@@ -1071,12 +1052,10 @@ class MaaManager:
|
||||
and hasattr(self, "index")
|
||||
and self.user_list[self.index]["status"] == "运行"
|
||||
):
|
||||
|
||||
await self.result_record()
|
||||
|
||||
# 导出结果
|
||||
if self.mode in ["自动代理", "人工排查"]:
|
||||
|
||||
# 更新用户数据
|
||||
await Config.ScriptConfig[self.script_id].UserData.load(
|
||||
await self.user_config.toDict()
|
||||
@@ -1207,7 +1186,6 @@ class MaaManager:
|
||||
)
|
||||
|
||||
for port in self.port_range:
|
||||
|
||||
ADB_address = f"{ADB_ip}{ADB_port + port}"
|
||||
|
||||
# 尝试通过ADB连接到指定地址
|
||||
@@ -1221,7 +1199,6 @@ class MaaManager:
|
||||
)
|
||||
|
||||
if "connected" in connect_result.stdout:
|
||||
|
||||
# 检查连接状态
|
||||
devices_result = subprocess.run(
|
||||
[self.ADB_path, "devices"],
|
||||
@@ -1232,7 +1209,6 @@ class MaaManager:
|
||||
encoding="utf-8",
|
||||
)
|
||||
if ADB_address in devices_result.stdout:
|
||||
|
||||
logger.info(f"ADB实际地址: {ADB_address}")
|
||||
|
||||
# 断开连接
|
||||
@@ -1250,9 +1226,9 @@ class MaaManager:
|
||||
await System.kill_process(self.maa_exe_path)
|
||||
with self.maa_set_path.open(mode="r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
data["Configurations"]["Default"][
|
||||
"Connect.Address"
|
||||
] = self.ADB_address
|
||||
data["Configurations"]["Default"]["Connect.Address"] = (
|
||||
self.ADB_address
|
||||
)
|
||||
data["Configurations"]["Default"]["Start.EmulatorWaitSeconds"] = "0"
|
||||
with self.maa_set_path.open(mode="w", encoding="utf-8") as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||
@@ -1279,7 +1255,6 @@ class MaaManager:
|
||||
)
|
||||
|
||||
if self.mode == "自动代理":
|
||||
|
||||
# 获取最近一条日志的时间
|
||||
latest_time = self.log_start_time
|
||||
for _ in self.maa_logs[::-1]:
|
||||
@@ -1302,7 +1277,6 @@ class MaaManager:
|
||||
self.maa_result = "MAA未能正确登录PRTS"
|
||||
|
||||
elif "任务已全部完成!" in log:
|
||||
|
||||
if "完成任务: StartUp" in log or "完成任务: 开始唤醒" in log:
|
||||
self.task_dict["WakeUp"] = "False"
|
||||
if "完成任务: Recruit" in log or "完成任务: 自动公招" in log:
|
||||
@@ -1383,7 +1357,6 @@ class MaaManager:
|
||||
logger.info(f"开始配置MAA运行参数: {mode}")
|
||||
|
||||
if self.mode != "设置脚本" and mode != "Update":
|
||||
|
||||
if self.cur_user_data.get("Info", "Server") == "Bilibili":
|
||||
self.agree_bilibili(True)
|
||||
else:
|
||||
@@ -1454,38 +1427,36 @@ class MaaManager:
|
||||
|
||||
# 自动代理配置
|
||||
if self.mode == "自动代理" and mode in ["Annihilation", "Routine"]:
|
||||
|
||||
if (self.index == len(self.user_list) - 1) or (
|
||||
self.user_config[
|
||||
uuid.UUID(self.user_list[self.index + 1]["user_id"])
|
||||
].get("Info", "Mode")
|
||||
== "详细"
|
||||
):
|
||||
data["Configurations"]["Default"][
|
||||
"MainFunction.PostActions"
|
||||
] = "12" # 完成后退出MAA和模拟器
|
||||
data["Configurations"]["Default"]["MainFunction.PostActions"] = (
|
||||
"12" # 完成后退出MAA和模拟器
|
||||
)
|
||||
else:
|
||||
|
||||
data["Configurations"]["Default"]["MainFunction.PostActions"] = (
|
||||
METHOD_BOOK[self.script_config.get("Run", "TaskTransitionMethod")]
|
||||
) # 完成后行为
|
||||
|
||||
data["Configurations"]["Default"][
|
||||
"Start.RunDirectly"
|
||||
] = "True" # 启动MAA后直接运行
|
||||
data["Configurations"]["Default"]["Start.RunDirectly"] = (
|
||||
"True" # 启动MAA后直接运行
|
||||
)
|
||||
data["Configurations"]["Default"]["Start.OpenEmulatorAfterLaunch"] = str(
|
||||
self.if_open_emulator
|
||||
) # 启动MAA后自动开启模拟器
|
||||
|
||||
data["Global"][
|
||||
"VersionUpdate.ScheduledUpdateCheck"
|
||||
] = "False" # 定时检查更新
|
||||
data["Global"][
|
||||
"VersionUpdate.AutoDownloadUpdatePackage"
|
||||
] = "True" # 自动下载更新包
|
||||
data["Global"][
|
||||
"VersionUpdate.AutoInstallUpdatePackage"
|
||||
] = "False" # 自动安装更新包
|
||||
data["Global"]["VersionUpdate.ScheduledUpdateCheck"] = (
|
||||
"False" # 定时检查更新
|
||||
)
|
||||
data["Global"]["VersionUpdate.AutoDownloadUpdatePackage"] = (
|
||||
"True" # 自动下载更新包
|
||||
)
|
||||
data["Global"]["VersionUpdate.AutoInstallUpdatePackage"] = (
|
||||
"False" # 自动安装更新包
|
||||
)
|
||||
|
||||
if Config.get("Function", "IfSilence"):
|
||||
data["Global"]["Start.MinimizeDirectly"] = "True" # 启动MAA后直接最小化
|
||||
@@ -1510,9 +1481,9 @@ class MaaManager:
|
||||
)
|
||||
|
||||
# 按预设设定任务
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.WakeUp.IsChecked"
|
||||
] = "True" # 开始唤醒
|
||||
data["Configurations"]["Default"]["TaskQueue.WakeUp.IsChecked"] = (
|
||||
"True" # 开始唤醒
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Recruiting.IsChecked"] = (
|
||||
self.task_dict["Recruiting"]
|
||||
) # 自动公招
|
||||
@@ -1584,49 +1555,47 @@ class MaaManager:
|
||||
) # 连战次数
|
||||
|
||||
if mode == "Annihilation":
|
||||
|
||||
data["Configurations"]["Default"][
|
||||
"MainFunction.Stage1"
|
||||
] = "Annihilation" # 主关卡
|
||||
data["Configurations"]["Default"][
|
||||
"MainFunction.Stage2"
|
||||
] = "" # 备选关卡1
|
||||
data["Configurations"]["Default"][
|
||||
"MainFunction.Stage3"
|
||||
] = "" # 备选关卡2
|
||||
data["Configurations"]["Default"][
|
||||
"Fight.RemainingSanityStage"
|
||||
] = "" # 剩余理智关卡
|
||||
data["Configurations"]["Default"][
|
||||
"MainFunction.Series.Quantity"
|
||||
] = "1" # 连战次数
|
||||
data["Configurations"]["Default"]["MainFunction.Stage1"] = (
|
||||
"Annihilation" # 主关卡
|
||||
)
|
||||
data["Configurations"]["Default"]["MainFunction.Stage2"] = (
|
||||
"" # 备选关卡1
|
||||
)
|
||||
data["Configurations"]["Default"]["MainFunction.Stage3"] = (
|
||||
"" # 备选关卡2
|
||||
)
|
||||
data["Configurations"]["Default"]["Fight.RemainingSanityStage"] = (
|
||||
"" # 剩余理智关卡
|
||||
)
|
||||
data["Configurations"]["Default"]["MainFunction.Series.Quantity"] = (
|
||||
"1" # 连战次数
|
||||
)
|
||||
data["Configurations"]["Default"][
|
||||
"MainFunction.Annihilation.UseCustom"
|
||||
] = "True" # 自定义剿灭关卡
|
||||
data["Configurations"]["Default"]["MainFunction.Annihilation.Stage"] = (
|
||||
self.cur_user_data.get("Info", "Annihilation")
|
||||
) # 自定义剿灭关卡号
|
||||
data["Configurations"]["Default"][
|
||||
"Penguin.IsDrGrandet"
|
||||
] = "False" # 博朗台模式
|
||||
data["Configurations"]["Default"][
|
||||
"GUI.CustomStageCode"
|
||||
] = "True" # 手动输入关卡名
|
||||
data["Configurations"]["Default"][
|
||||
"GUI.UseAlternateStage"
|
||||
] = "False" # 使用备选关卡
|
||||
data["Configurations"]["Default"][
|
||||
"Fight.UseRemainingSanityStage"
|
||||
] = "False" # 使用剩余理智
|
||||
data["Configurations"]["Default"][
|
||||
"Fight.UseExpiringMedicine"
|
||||
] = "True" # 无限吃48小时内过期的理智药
|
||||
data["Configurations"]["Default"][
|
||||
"GUI.HideSeries"
|
||||
] = "False" # 隐藏连战次数
|
||||
data["Configurations"]["Default"]["Penguin.IsDrGrandet"] = (
|
||||
"False" # 博朗台模式
|
||||
)
|
||||
data["Configurations"]["Default"]["GUI.CustomStageCode"] = (
|
||||
"True" # 手动输入关卡名
|
||||
)
|
||||
data["Configurations"]["Default"]["GUI.UseAlternateStage"] = (
|
||||
"False" # 使用备选关卡
|
||||
)
|
||||
data["Configurations"]["Default"]["Fight.UseRemainingSanityStage"] = (
|
||||
"False" # 使用剩余理智
|
||||
)
|
||||
data["Configurations"]["Default"]["Fight.UseExpiringMedicine"] = (
|
||||
"True" # 无限吃48小时内过期的理智药
|
||||
)
|
||||
data["Configurations"]["Default"]["GUI.HideSeries"] = (
|
||||
"False" # 隐藏连战次数
|
||||
)
|
||||
|
||||
elif mode == "Routine":
|
||||
|
||||
data["Configurations"]["Default"]["MainFunction.Stage1"] = (
|
||||
plan_data.get("Stage") if plan_data.get("Stage", "-") != "-" else ""
|
||||
) # 主关卡
|
||||
@@ -1650,35 +1619,32 @@ class MaaManager:
|
||||
if plan_data.get("Stage_Remain", "-") != "-"
|
||||
else ""
|
||||
) # 剩余理智关卡
|
||||
data["Configurations"]["Default"][
|
||||
"GUI.UseAlternateStage"
|
||||
] = "True" # 备选关卡
|
||||
data["Configurations"]["Default"]["GUI.UseAlternateStage"] = (
|
||||
"True" # 备选关卡
|
||||
)
|
||||
data["Configurations"]["Default"]["Fight.UseRemainingSanityStage"] = (
|
||||
"True" if plan_data.get("Stage_Remain", "-") != "-" else "False"
|
||||
) # 使用剩余理智
|
||||
|
||||
if self.cur_user_data.get("Info", "Mode") == "简洁":
|
||||
|
||||
data["Configurations"]["Default"][
|
||||
"Penguin.IsDrGrandet"
|
||||
] = "False" # 博朗台模式
|
||||
data["Configurations"]["Default"][
|
||||
"GUI.CustomStageCode"
|
||||
] = "True" # 手动输入关卡名
|
||||
data["Configurations"]["Default"][
|
||||
"Fight.UseExpiringMedicine"
|
||||
] = "True" # 无限吃48小时内过期的理智药
|
||||
data["Configurations"]["Default"]["Penguin.IsDrGrandet"] = (
|
||||
"False" # 博朗台模式
|
||||
)
|
||||
data["Configurations"]["Default"]["GUI.CustomStageCode"] = (
|
||||
"True" # 手动输入关卡名
|
||||
)
|
||||
data["Configurations"]["Default"]["Fight.UseExpiringMedicine"] = (
|
||||
"True" # 无限吃48小时内过期的理智药
|
||||
)
|
||||
# 自定义基建配置
|
||||
if self.cur_user_data.get("Info", "InfrastMode") == "Custom":
|
||||
|
||||
if (
|
||||
Path.cwd()
|
||||
/ f"data/{self.script_id}/{self.user_list[self.index]['user_id']}/Infrastructure/infrastructure.json"
|
||||
).exists():
|
||||
|
||||
data["Configurations"]["Default"][
|
||||
"Infrast.InfrastMode"
|
||||
] = "Custom" # 基建模式
|
||||
data["Configurations"]["Default"]["Infrast.InfrastMode"] = (
|
||||
"Custom" # 基建模式
|
||||
)
|
||||
data["Configurations"]["Default"][
|
||||
"Infrast.CustomInfrastPlanIndex"
|
||||
] = self.cur_user_data.get(
|
||||
@@ -1718,7 +1684,6 @@ class MaaManager:
|
||||
) # 基建模式
|
||||
|
||||
elif self.cur_user_data.get("Info", "Mode") == "详细":
|
||||
|
||||
# 基建模式
|
||||
if (
|
||||
data["Configurations"]["Default"]["Infrast.InfrastMode"]
|
||||
@@ -1732,28 +1697,27 @@ class MaaManager:
|
||||
|
||||
# 人工排查配置
|
||||
elif self.mode == "人工排查" and self.cur_user_data is not None:
|
||||
|
||||
data["Configurations"]["Default"][
|
||||
"MainFunction.PostActions"
|
||||
] = "8" # 完成后退出MAA
|
||||
data["Configurations"]["Default"][
|
||||
"Start.RunDirectly"
|
||||
] = "True" # 启动MAA后直接运行
|
||||
data["Configurations"]["Default"]["MainFunction.PostActions"] = (
|
||||
"8" # 完成后退出MAA
|
||||
)
|
||||
data["Configurations"]["Default"]["Start.RunDirectly"] = (
|
||||
"True" # 启动MAA后直接运行
|
||||
)
|
||||
data["Global"]["Start.MinimizeDirectly"] = "True" # 启动MAA后直接最小化
|
||||
data["Global"]["GUI.UseTray"] = "True" # 显示托盘图标
|
||||
data["Global"]["GUI.MinimizeToTray"] = "True" # 最小化时隐藏至托盘
|
||||
data["Configurations"]["Default"]["Start.OpenEmulatorAfterLaunch"] = str(
|
||||
self.if_open_emulator
|
||||
) # 启动MAA后自动开启模拟器
|
||||
data["Global"][
|
||||
"VersionUpdate.ScheduledUpdateCheck"
|
||||
] = "False" # 定时检查更新
|
||||
data["Global"][
|
||||
"VersionUpdate.AutoDownloadUpdatePackage"
|
||||
] = "False" # 自动下载更新包
|
||||
data["Global"][
|
||||
"VersionUpdate.AutoInstallUpdatePackage"
|
||||
] = "False" # 自动安装更新包
|
||||
data["Global"]["VersionUpdate.ScheduledUpdateCheck"] = (
|
||||
"False" # 定时检查更新
|
||||
)
|
||||
data["Global"]["VersionUpdate.AutoDownloadUpdatePackage"] = (
|
||||
"False" # 自动下载更新包
|
||||
)
|
||||
data["Global"]["VersionUpdate.AutoInstallUpdatePackage"] = (
|
||||
"False" # 自动安装更新包
|
||||
)
|
||||
|
||||
# 客户端类型
|
||||
data["Configurations"]["Default"]["Start.ClientType"] = (
|
||||
@@ -1772,134 +1736,132 @@ class MaaManager:
|
||||
self.cur_user_data.get("Info", "Id")
|
||||
)
|
||||
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.WakeUp.IsChecked"
|
||||
] = "True" # 开始唤醒
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Recruiting.IsChecked"
|
||||
] = "False" # 自动公招
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Base.IsChecked"
|
||||
] = "False" # 基建换班
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Combat.IsChecked"
|
||||
] = "False" # 刷理智
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Mission.IsChecked"
|
||||
] = "False" # 领取奖励
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Mall.IsChecked"
|
||||
] = "False" # 获取信用及购物
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.AutoRoguelike.IsChecked"
|
||||
] = "False" # 自动肉鸽
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Reclamation.IsChecked"
|
||||
] = "False" # 生息演算
|
||||
data["Configurations"]["Default"]["TaskQueue.WakeUp.IsChecked"] = (
|
||||
"True" # 开始唤醒
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Recruiting.IsChecked"] = (
|
||||
"False" # 自动公招
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Base.IsChecked"] = (
|
||||
"False" # 基建换班
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Combat.IsChecked"] = (
|
||||
"False" # 刷理智
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Mission.IsChecked"] = (
|
||||
"False" # 领取奖励
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Mall.IsChecked"] = (
|
||||
"False" # 获取信用及购物
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.AutoRoguelike.IsChecked"] = (
|
||||
"False" # 自动肉鸽
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Reclamation.IsChecked"] = (
|
||||
"False" # 生息演算
|
||||
)
|
||||
|
||||
# 设置脚本配置
|
||||
elif self.mode == "设置脚本":
|
||||
|
||||
data["Configurations"]["Default"][
|
||||
"MainFunction.PostActions"
|
||||
] = "0" # 完成后无动作
|
||||
data["Configurations"]["Default"][
|
||||
"Start.RunDirectly"
|
||||
] = "False" # 启动MAA后直接运行
|
||||
data["Configurations"]["Default"][
|
||||
"Start.OpenEmulatorAfterLaunch"
|
||||
] = "False" # 启动MAA后自动开启模拟器
|
||||
data["Global"][
|
||||
"VersionUpdate.ScheduledUpdateCheck"
|
||||
] = "False" # 定时检查更新
|
||||
data["Global"][
|
||||
"VersionUpdate.AutoDownloadUpdatePackage"
|
||||
] = "False" # 自动下载更新包
|
||||
data["Global"][
|
||||
"VersionUpdate.AutoInstallUpdatePackage"
|
||||
] = "False" # 自动安装更新包
|
||||
data["Configurations"]["Default"]["MainFunction.PostActions"] = (
|
||||
"0" # 完成后无动作
|
||||
)
|
||||
data["Configurations"]["Default"]["Start.RunDirectly"] = (
|
||||
"False" # 启动MAA后直接运行
|
||||
)
|
||||
data["Configurations"]["Default"]["Start.OpenEmulatorAfterLaunch"] = (
|
||||
"False" # 启动MAA后自动开启模拟器
|
||||
)
|
||||
data["Global"]["VersionUpdate.ScheduledUpdateCheck"] = (
|
||||
"False" # 定时检查更新
|
||||
)
|
||||
data["Global"]["VersionUpdate.AutoDownloadUpdatePackage"] = (
|
||||
"False" # 自动下载更新包
|
||||
)
|
||||
data["Global"]["VersionUpdate.AutoInstallUpdatePackage"] = (
|
||||
"False" # 自动安装更新包
|
||||
)
|
||||
|
||||
if Config.get("Function", "IfSilence"):
|
||||
data["Global"][
|
||||
"Start.MinimizeDirectly"
|
||||
] = "False" # 启动MAA后直接最小化
|
||||
data["Global"]["Start.MinimizeDirectly"] = (
|
||||
"False" # 启动MAA后直接最小化
|
||||
)
|
||||
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.WakeUp.IsChecked"
|
||||
] = "False" # 开始唤醒
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Recruiting.IsChecked"
|
||||
] = "False" # 自动公招
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Base.IsChecked"
|
||||
] = "False" # 基建换班
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Combat.IsChecked"
|
||||
] = "False" # 刷理智
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Mission.IsChecked"
|
||||
] = "False" # 领取奖励
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Mall.IsChecked"
|
||||
] = "False" # 获取信用及购物
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.AutoRoguelike.IsChecked"
|
||||
] = "False" # 自动肉鸽
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Reclamation.IsChecked"
|
||||
] = "False" # 生息演算
|
||||
data["Configurations"]["Default"]["TaskQueue.WakeUp.IsChecked"] = (
|
||||
"False" # 开始唤醒
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Recruiting.IsChecked"] = (
|
||||
"False" # 自动公招
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Base.IsChecked"] = (
|
||||
"False" # 基建换班
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Combat.IsChecked"] = (
|
||||
"False" # 刷理智
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Mission.IsChecked"] = (
|
||||
"False" # 领取奖励
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Mall.IsChecked"] = (
|
||||
"False" # 获取信用及购物
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.AutoRoguelike.IsChecked"] = (
|
||||
"False" # 自动肉鸽
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Reclamation.IsChecked"] = (
|
||||
"False" # 生息演算
|
||||
)
|
||||
|
||||
elif mode == "Update":
|
||||
|
||||
data["Configurations"]["Default"][
|
||||
"MainFunction.PostActions"
|
||||
] = "0" # 完成后无动作
|
||||
data["Configurations"]["Default"][
|
||||
"Start.RunDirectly"
|
||||
] = "False" # 启动MAA后直接运行
|
||||
data["Configurations"]["Default"][
|
||||
"Start.OpenEmulatorAfterLaunch"
|
||||
] = "False" # 启动MAA后自动开启模拟器
|
||||
data["Configurations"]["Default"]["MainFunction.PostActions"] = (
|
||||
"0" # 完成后无动作
|
||||
)
|
||||
data["Configurations"]["Default"]["Start.RunDirectly"] = (
|
||||
"False" # 启动MAA后直接运行
|
||||
)
|
||||
data["Configurations"]["Default"]["Start.OpenEmulatorAfterLaunch"] = (
|
||||
"False" # 启动MAA后自动开启模拟器
|
||||
)
|
||||
data["Global"]["Start.MinimizeDirectly"] = "True" # 启动MAA后直接最小化
|
||||
data["Global"]["GUI.UseTray"] = "True" # 显示托盘图标
|
||||
data["Global"]["GUI.MinimizeToTray"] = "True" # 最小化时隐藏至托盘
|
||||
data["Global"][
|
||||
"VersionUpdate.package"
|
||||
] = self.maa_update_package # 更新包路径
|
||||
data["Global"]["VersionUpdate.package"] = (
|
||||
self.maa_update_package
|
||||
) # 更新包路径
|
||||
|
||||
data["Global"][
|
||||
"VersionUpdate.ScheduledUpdateCheck"
|
||||
] = "False" # 定时检查更新
|
||||
data["Global"][
|
||||
"VersionUpdate.AutoDownloadUpdatePackage"
|
||||
] = "False" # 自动下载更新包
|
||||
data["Global"][
|
||||
"VersionUpdate.AutoInstallUpdatePackage"
|
||||
] = "True" # 自动安装更新包
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.WakeUp.IsChecked"
|
||||
] = "False" # 开始唤醒
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Recruiting.IsChecked"
|
||||
] = "False" # 自动公招
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Base.IsChecked"
|
||||
] = "False" # 基建换班
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Combat.IsChecked"
|
||||
] = "False" # 刷理智
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Mission.IsChecked"
|
||||
] = "False" # 领取奖励
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Mall.IsChecked"
|
||||
] = "False" # 获取信用及购物
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.AutoRoguelike.IsChecked"
|
||||
] = "False" # 自动肉鸽
|
||||
data["Configurations"]["Default"][
|
||||
"TaskQueue.Reclamation.IsChecked"
|
||||
] = "False" # 生息演算
|
||||
data["Global"]["VersionUpdate.ScheduledUpdateCheck"] = (
|
||||
"False" # 定时检查更新
|
||||
)
|
||||
data["Global"]["VersionUpdate.AutoDownloadUpdatePackage"] = (
|
||||
"False" # 自动下载更新包
|
||||
)
|
||||
data["Global"]["VersionUpdate.AutoInstallUpdatePackage"] = (
|
||||
"True" # 自动安装更新包
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.WakeUp.IsChecked"] = (
|
||||
"False" # 开始唤醒
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Recruiting.IsChecked"] = (
|
||||
"False" # 自动公招
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Base.IsChecked"] = (
|
||||
"False" # 基建换班
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Combat.IsChecked"] = (
|
||||
"False" # 刷理智
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Mission.IsChecked"] = (
|
||||
"False" # 领取奖励
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Mall.IsChecked"] = (
|
||||
"False" # 获取信用及购物
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.AutoRoguelike.IsChecked"] = (
|
||||
"False" # 自动肉鸽
|
||||
)
|
||||
data["Configurations"]["Default"]["TaskQueue.Reclamation.IsChecked"] = (
|
||||
"False" # 生息演算
|
||||
)
|
||||
|
||||
# 启动模拟器仅生效一次
|
||||
if self.mode != "设置脚本" and mode != "Update" and self.if_open_emulator:
|
||||
@@ -1995,7 +1957,6 @@ class MaaManager:
|
||||
)
|
||||
|
||||
elif mode == "统计信息":
|
||||
|
||||
# 生成文本通知内容
|
||||
formatted = []
|
||||
if "drop_statistics" in message:
|
||||
@@ -2030,7 +1991,6 @@ class MaaManager:
|
||||
|
||||
# 发送全局通知
|
||||
if Config.get("Notify", "IfSendStatistic"):
|
||||
|
||||
if Config.get("Notify", "IfSendMail"):
|
||||
await Notify.send_mail(
|
||||
"网页", title, message_html, Config.get("Notify", "ToAddress")
|
||||
@@ -2053,7 +2013,6 @@ class MaaManager:
|
||||
if self.cur_user_data.get("Notify", "Enabled") and self.cur_user_data.get(
|
||||
"Notify", "IfSendStatistic"
|
||||
):
|
||||
|
||||
# 发送邮件通知
|
||||
if self.cur_user_data.get("Notify", "IfSendMail"):
|
||||
await Notify.send_mail(
|
||||
@@ -2078,7 +2037,6 @@ class MaaManager:
|
||||
)
|
||||
|
||||
elif mode == "公招六星":
|
||||
|
||||
# 生成HTML通知内容
|
||||
template = env.get_template("MAA_six_star.html")
|
||||
|
||||
@@ -2086,7 +2044,6 @@ class MaaManager:
|
||||
|
||||
# 发送全局通知
|
||||
if Config.get("Notify", "IfSendSixStar"):
|
||||
|
||||
if Config.get("Notify", "IfSendMail"):
|
||||
await Notify.send_mail(
|
||||
"网页", title, message_html, Config.get("Notify", "ToAddress")
|
||||
@@ -2107,7 +2064,6 @@ class MaaManager:
|
||||
if self.cur_user_data.get("Notify", "Enabled") and self.cur_user_data.get(
|
||||
"Notify", "IfSendSixStar"
|
||||
):
|
||||
|
||||
# 发送邮件通知
|
||||
if self.cur_user_data.get("Notify", "IfSendMail"):
|
||||
await Notify.send_mail(
|
||||
|
||||
@@ -1 +1,630 @@
|
||||
.log-entry.error .log-message {
|
||||
<template>
|
||||
<div class="backend-launch-page">
|
||||
<div class="section">
|
||||
<h3 class="section-title">🚀 后端服务控制</h3>
|
||||
|
||||
<!-- 后端状态显示 -->
|
||||
<div class="status-card" :class="{ running: isBackendRunning, stopped: !isBackendRunning }">
|
||||
<div class="status-indicator">
|
||||
<span class="status-dot" :class="{ active: isBackendRunning }"></span>
|
||||
<span class="status-text">
|
||||
{{ isBackendRunning ? '运行中' : '已停止' }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="backendPid" class="pid-info">
|
||||
PID: {{ backendPid }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 控制按钮 -->
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
@click="startBackend"
|
||||
:disabled="isLoading || isBackendRunning"
|
||||
class="action-btn start-btn"
|
||||
>
|
||||
<span v-if="isLoading" class="loading-spinner">⏳</span>
|
||||
<span v-else>▶️</span>
|
||||
启动后端
|
||||
</button>
|
||||
|
||||
<button
|
||||
@click="stopBackend"
|
||||
:disabled="isLoading || !isBackendRunning"
|
||||
class="action-btn stop-btn"
|
||||
>
|
||||
<span v-if="isLoading" class="loading-spinner">⏳</span>
|
||||
<span v-else>⏹️</span>
|
||||
停止后端
|
||||
</button>
|
||||
|
||||
<button
|
||||
@click="refreshStatus"
|
||||
:disabled="isLoading"
|
||||
class="action-btn refresh-btn"
|
||||
>
|
||||
<span v-if="isLoading" class="loading-spinner">⏳</span>
|
||||
<span v-else>🔄</span>
|
||||
刷新状态
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 操作结果显示 -->
|
||||
<div v-if="lastResult" class="result-card" :class="{ success: lastResult.success, error: !lastResult.success }">
|
||||
<div class="result-title">
|
||||
{{ lastResult.success ? '✅ 操作成功' : '❌ 操作失败' }}
|
||||
</div>
|
||||
<div v-if="lastResult.message" class="result-message">
|
||||
{{ lastResult.message }}
|
||||
</div>
|
||||
<div v-if="lastResult.error" class="result-error">
|
||||
错误: {{ lastResult.error }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 进程信息 -->
|
||||
<div class="section">
|
||||
<h3 class="section-title">📊 进程信息</h3>
|
||||
|
||||
<div class="process-info">
|
||||
<div class="info-row">
|
||||
<span class="info-label">Python路径:</span>
|
||||
<span class="info-value">{{ pythonPath || '未检测到' }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-label">主文件:</span>
|
||||
<span class="info-value">{{ mainPyPath || '未检测到' }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-label">工作目录:</span>
|
||||
<span class="info-value">{{ workingDir || '未知' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button @click="getProcessInfo" :disabled="isLoading" class="action-btn info-btn">
|
||||
<span v-if="isLoading" class="loading-spinner">⏳</span>
|
||||
<span v-else>🔍</span>
|
||||
获取进程信息
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 快速操作 -->
|
||||
<div class="section">
|
||||
<h3 class="section-title">⚡ 快速操作</h3>
|
||||
|
||||
<div class="quick-actions">
|
||||
<button @click="restartBackend" :disabled="isLoading" class="action-btn restart-btn">
|
||||
<span v-if="isLoading" class="loading-spinner">⏳</span>
|
||||
<span v-else>🔄</span>
|
||||
重启后端
|
||||
</button>
|
||||
|
||||
<button @click="forceKillProcesses" :disabled="isLoading" class="action-btn kill-btn">
|
||||
<span v-if="isLoading" class="loading-spinner">⏳</span>
|
||||
<span v-else>💀</span>
|
||||
强制结束所有进程
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 日志区域 -->
|
||||
<div class="section">
|
||||
<h3 class="section-title">📝 操作日志</h3>
|
||||
|
||||
<div class="log-container">
|
||||
<div v-if="logs.length === 0" class="no-logs">
|
||||
暂无日志记录
|
||||
</div>
|
||||
<div v-else class="log-entries">
|
||||
<div
|
||||
v-for="(log, index) in logs"
|
||||
:key="index"
|
||||
class="log-entry"
|
||||
:class="log.type"
|
||||
>
|
||||
<span class="log-time">{{ log.time }}</span>
|
||||
<span class="log-message">{{ log.message }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button @click="clearLogs" class="action-btn clear-btn">
|
||||
🗑️ 清空日志
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
|
||||
// 临时的类型断言,确保能访问到完整的electronAPI
|
||||
const electronAPI = (window as any).electronAPI
|
||||
|
||||
// 状态管理
|
||||
const isBackendRunning = ref(false)
|
||||
const isLoading = ref(false)
|
||||
const backendPid = ref<number | null>(null)
|
||||
const lastResult = ref<{ success: boolean; message?: string; error?: string } | null>(null)
|
||||
|
||||
// 进程信息
|
||||
const pythonPath = ref<string>('')
|
||||
const mainPyPath = ref<string>('')
|
||||
const workingDir = ref<string>('')
|
||||
|
||||
// 日志管理
|
||||
const logs = ref<Array<{ time: string; message: string; type: 'info' | 'success' | 'error' }>>([])
|
||||
|
||||
// 添加日志
|
||||
const addLog = (message: string, type: 'info' | 'success' | 'error' = 'info') => {
|
||||
const now = new Date()
|
||||
const time = now.toLocaleTimeString()
|
||||
logs.value.unshift({ time, message, type })
|
||||
|
||||
// 限制日志数量
|
||||
if (logs.value.length > 50) {
|
||||
logs.value = logs.value.slice(0, 50)
|
||||
}
|
||||
}
|
||||
|
||||
// 清空日志
|
||||
const clearLogs = () => {
|
||||
logs.value = []
|
||||
addLog('日志已清空', 'info')
|
||||
}
|
||||
|
||||
// 启动后端
|
||||
const startBackend = async () => {
|
||||
if (isLoading.value) return
|
||||
|
||||
isLoading.value = true
|
||||
lastResult.value = null
|
||||
addLog('正在启动后端服务...', 'info')
|
||||
|
||||
try {
|
||||
const result = await electronAPI.startBackend()
|
||||
|
||||
if (result.success) {
|
||||
lastResult.value = { success: true, message: '后端服务启动成功' }
|
||||
addLog('✅ 后端服务启动成功', 'success')
|
||||
await refreshStatus()
|
||||
} else {
|
||||
lastResult.value = { success: false, error: result.error }
|
||||
addLog(`❌ 后端服务启动失败: ${result.error}`, 'error')
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : String(error)
|
||||
lastResult.value = { success: false, error: errorMsg }
|
||||
addLog(`❌ 启动后端时出现异常: ${errorMsg}`, 'error')
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 停止后端
|
||||
const stopBackend = async () => {
|
||||
if (isLoading.value) return
|
||||
|
||||
isLoading.value = true
|
||||
lastResult.value = null
|
||||
addLog('正在停止后端服务...', 'info')
|
||||
|
||||
try {
|
||||
// 检查stopBackend方法是否存在
|
||||
if (electronAPI.stopBackend) {
|
||||
const result = await electronAPI.stopBackend()
|
||||
|
||||
if (result.success) {
|
||||
lastResult.value = { success: true, message: '后端服务已停止' }
|
||||
addLog('✅ 后端服务已停止', 'success')
|
||||
await refreshStatus()
|
||||
} else {
|
||||
lastResult.value = { success: false, error: result.error }
|
||||
addLog(`❌ 停止后端服务失败: ${result.error}`, 'error')
|
||||
}
|
||||
} else {
|
||||
// 如果没有stopBackend方法,使用强制结束进程的方式
|
||||
addLog('ℹ️ 使用强制结束进程的方式停止后端', 'info')
|
||||
await forceKillProcesses()
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : String(error)
|
||||
lastResult.value = { success: false, error: errorMsg }
|
||||
addLog(`❌ 停止后端时出现异常: ${errorMsg}`, 'error')
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 重启后端
|
||||
const restartBackend = async () => {
|
||||
if (isLoading.value) return
|
||||
|
||||
addLog('正在重启后端服务...', 'info')
|
||||
|
||||
// 先停止
|
||||
if (isBackendRunning.value) {
|
||||
await stopBackend()
|
||||
// 等待一秒确保完全停止
|
||||
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||
}
|
||||
|
||||
// 再启动
|
||||
await startBackend()
|
||||
}
|
||||
|
||||
// 强制结束所有相关进程
|
||||
const forceKillProcesses = async () => {
|
||||
if (isLoading.value) return
|
||||
|
||||
isLoading.value = true
|
||||
addLog('正在强制结束所有相关进程...', 'info')
|
||||
|
||||
try {
|
||||
const result = await electronAPI.killAllProcesses()
|
||||
|
||||
if (result.success) {
|
||||
lastResult.value = { success: true, message: '所有相关进程已强制结束' }
|
||||
addLog('✅ 所有相关进程已强制结束', 'success')
|
||||
await refreshStatus()
|
||||
} else {
|
||||
lastResult.value = { success: false, error: result.error }
|
||||
addLog(`❌ 强制结束进程失败: ${result.error}`, 'error')
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : String(error)
|
||||
lastResult.value = { success: false, error: errorMsg }
|
||||
addLog(`❌ 强制结束进程时出现异常: ${errorMsg}`, 'error')
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 刷新状态
|
||||
const refreshStatus = async () => {
|
||||
if (isLoading.value) return
|
||||
|
||||
isLoading.value = true
|
||||
addLog('正在刷新后端状态...', 'info')
|
||||
|
||||
try {
|
||||
// 获取相关进程信息
|
||||
const processes = await electronAPI.getRelatedProcesses()
|
||||
|
||||
// 检查是否有Python进程在运行main.py
|
||||
const backendProcess = processes.find((proc: any) =>
|
||||
proc.command && proc.command.includes('main.py')
|
||||
)
|
||||
|
||||
if (backendProcess) {
|
||||
isBackendRunning.value = true
|
||||
backendPid.value = backendProcess.pid
|
||||
addLog(`✅ 检测到后端进程 (PID: ${backendProcess.pid})`, 'success')
|
||||
} else {
|
||||
isBackendRunning.value = false
|
||||
backendPid.value = null
|
||||
addLog('ℹ️ 未检测到后端进程', 'info')
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : String(error)
|
||||
addLog(`❌ 刷新状态失败: ${errorMsg}`, 'error')
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 获取进程信息
|
||||
const getProcessInfo = async () => {
|
||||
if (isLoading.value) return
|
||||
|
||||
isLoading.value = true
|
||||
addLog('正在获取进程信息...', 'info')
|
||||
|
||||
try {
|
||||
// 这里可以调用一些API来获取Python路径等信息
|
||||
// 暂时使用模拟数据
|
||||
pythonPath.value = 'environment/python/python.exe'
|
||||
mainPyPath.value = 'main.py'
|
||||
workingDir.value = window.location.origin
|
||||
|
||||
addLog('✅ 进程信息获取完成', 'success')
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : String(error)
|
||||
addLog(`❌ 获取进程信息失败: ${errorMsg}`, 'error')
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 定时刷新状态
|
||||
let statusInterval: NodeJS.Timeout | null = null
|
||||
|
||||
onMounted(() => {
|
||||
addLog('📱 后端控制面板已加载', 'info')
|
||||
|
||||
// 初始化时获取状态
|
||||
refreshStatus()
|
||||
getProcessInfo()
|
||||
|
||||
// 每5秒自动刷新状态
|
||||
statusInterval = setInterval(() => {
|
||||
refreshStatus()
|
||||
}, 5000)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (statusInterval) {
|
||||
clearInterval(statusInterval)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.backend-launch-page {
|
||||
font-size: 11px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.section:last-child {
|
||||
border-bottom: none;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
margin: 0 0 8px 0;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: #4caf50;
|
||||
}
|
||||
|
||||
/* 状态卡片 */
|
||||
.status-card {
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 8px;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.status-card.running {
|
||||
background: rgba(76, 175, 80, 0.1);
|
||||
border-color: rgba(76, 175, 80, 0.3);
|
||||
}
|
||||
|
||||
.status-card.stopped {
|
||||
background: rgba(244, 67, 54, 0.1);
|
||||
border-color: rgba(244, 67, 54, 0.3);
|
||||
}
|
||||
|
||||
.status-indicator {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.status-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: #f44336;
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
.status-dot.active {
|
||||
background: #4caf50;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% { opacity: 1; }
|
||||
50% { opacity: 0.5; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.pid-info {
|
||||
margin-top: 4px;
|
||||
font-size: 10px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
/* 按钮样式 */
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 6px 8px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 4px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
font-size: 10px;
|
||||
transition: all 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.action-btn:hover:not(:disabled) {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.action-btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.start-btn:hover:not(:disabled) {
|
||||
background: rgba(76, 175, 80, 0.3);
|
||||
border-color: rgba(76, 175, 80, 0.5);
|
||||
}
|
||||
|
||||
.stop-btn:hover:not(:disabled) {
|
||||
background: rgba(244, 67, 54, 0.3);
|
||||
border-color: rgba(244, 67, 54, 0.5);
|
||||
}
|
||||
|
||||
.restart-btn:hover:not(:disabled) {
|
||||
background: rgba(255, 193, 7, 0.3);
|
||||
border-color: rgba(255, 193, 7, 0.5);
|
||||
}
|
||||
|
||||
.kill-btn:hover:not(:disabled) {
|
||||
background: rgba(156, 39, 176, 0.3);
|
||||
border-color: rgba(156, 39, 176, 0.5);
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* 结果卡片 */
|
||||
.result-card {
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 8px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.result-card.success {
|
||||
background: rgba(76, 175, 80, 0.1);
|
||||
border-color: rgba(76, 175, 80, 0.3);
|
||||
}
|
||||
|
||||
.result-card.error {
|
||||
background: rgba(244, 67, 54, 0.1);
|
||||
border-color: rgba(244, 67, 54, 0.3);
|
||||
}
|
||||
|
||||
.result-title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.result-message, .result-error {
|
||||
font-size: 10px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.result-error {
|
||||
color: #ff6b6b;
|
||||
}
|
||||
|
||||
/* 进程信息 */
|
||||
.process-info {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
margin-bottom: 4px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
width: 60px;
|
||||
color: #888;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
color: #fff;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* 日志区域 */
|
||||
.log-container {
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 4px;
|
||||
max-height: 120px;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.no-logs {
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
color: #888;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.log-entries {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.log-entry {
|
||||
padding: 2px 4px;
|
||||
font-size: 9px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.log-entry:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.log-entry.success {
|
||||
color: #4caf50;
|
||||
}
|
||||
|
||||
.log-entry.error {
|
||||
color: #f44336;
|
||||
}
|
||||
|
||||
.log-entry.info {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.log-time {
|
||||
color: #666;
|
||||
font-size: 8px;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.log-message {
|
||||
flex: 1;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.log-container::-webkit-scrollbar {
|
||||
width: 3px;
|
||||
}
|
||||
|
||||
.log-container::-webkit-scrollbar-track {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.log-container::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 2px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -74,7 +74,7 @@ import { onMounted, onUnmounted, ref } from 'vue'
|
||||
import { useWebSocket } from '@/composables/useWebSocket'
|
||||
import { logger } from '@/utils/logger'
|
||||
|
||||
const { subscribe, unsubscribe, sendRaw, getConnectionInfo } = useWebSocket()
|
||||
const { subscribe, unsubscribe, getConnectionInfo } = useWebSocket()
|
||||
|
||||
// 测试状态
|
||||
const isTesting = ref(false)
|
||||
@@ -165,27 +165,39 @@ const directTriggerModal = () => {
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
// 发送WebSocket消息来模拟接收消息
|
||||
// 直接调用弹窗API测试功能
|
||||
const simulateMessage = (messageData: any) => {
|
||||
logger.info('[调试工具] 发送模拟消息:', messageData)
|
||||
|
||||
// 检查连接状态
|
||||
const connInfo = getConnectionInfo()
|
||||
if (connInfo.status !== '已连接') {
|
||||
logger.warn('[调试工具] WebSocket未连接,无法发送消息')
|
||||
lastResponse.value = '发送失败: WebSocket未连接'
|
||||
return
|
||||
}
|
||||
logger.info('[调试工具] 直接测试弹窗功能:', messageData)
|
||||
|
||||
try {
|
||||
// 使用sendRaw直接发送Message类型的消息
|
||||
sendRaw('Message', messageData)
|
||||
// 检查是否在Electron环境
|
||||
if (typeof window !== 'undefined' && (window as any).electronAPI?.showQuestionDialog) {
|
||||
// 直接调用Electron的弹窗API进行测试
|
||||
(window as any).electronAPI.showQuestionDialog({
|
||||
title: messageData.title || '测试标题',
|
||||
message: messageData.message || '测试消息',
|
||||
options: messageData.options || ['确定', '取消'],
|
||||
messageId: messageData.message_id || 'test-' + Date.now()
|
||||
}).then((result: boolean) => {
|
||||
logger.info('[调试工具] 弹窗测试结果:', result)
|
||||
const choice = result ? '确认' : '取消'
|
||||
lastResponse.value = `用户选择: ${choice}`
|
||||
addTestHistory('弹窗测试', choice)
|
||||
}).catch((error: any) => {
|
||||
logger.error('[调试工具] 弹窗测试失败:', error)
|
||||
lastResponse.value = '弹窗测试失败: ' + (error?.message || '未知错误')
|
||||
})
|
||||
} else {
|
||||
logger.warn('[调试工具] 不在Electron环境中或API不可用,使用浏览器confirm作为备用')
|
||||
const result = confirm(`${messageData.title || '测试'}\n\n${messageData.message || '这是测试消息'}`)
|
||||
const choice = result ? '确认' : '取消'
|
||||
lastResponse.value = `用户选择: ${choice} (浏览器备用)`
|
||||
addTestHistory('浏览器备用测试', choice)
|
||||
}
|
||||
|
||||
logger.info('[调试工具] 消息已发送到WebSocket')
|
||||
lastResponse.value = '消息已发送,等待弹窗显示...'
|
||||
} catch (error: any) {
|
||||
logger.error('[调试工具] 发送消息失败:', error)
|
||||
lastResponse.value = '发送失败: ' + (error?.message || '未知错误')
|
||||
logger.error('[调试工具] 测试弹窗失败:', error)
|
||||
lastResponse.value = '测试失败: ' + (error?.message || '未知错误')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,22 +44,28 @@ import RouteInfoPage from './RouteInfoPage.vue'
|
||||
import EnvironmentPage from './EnvironmentPage.vue'
|
||||
import QuickNavPage from './QuickNavPage.vue'
|
||||
import MessageTestPage from './MessageTestPage.vue'
|
||||
import BackendLaunchPage from './BackendLaunchPage.vue'
|
||||
|
||||
// 调试页面配置
|
||||
const tabs = [
|
||||
{ key: 'route', title: '路由', icon: '🛣️', component: RouteInfoPage },
|
||||
{ key: 'env', title: '环境', icon: '⚙️', component: EnvironmentPage },
|
||||
{ key: 'nav', title: '导航', icon: '🚀', component: QuickNavPage },
|
||||
{ key: 'backend', title: '后端', icon: '🚀', component: BackendLaunchPage },
|
||||
{ key: 'nav', title: '导航', icon: '🧭', component: QuickNavPage },
|
||||
{ key: 'message', title: '消息', icon: '💬', component: MessageTestPage },
|
||||
]
|
||||
|
||||
// 开发环境检测
|
||||
const isDev = ref(process.env.NODE_ENV === 'development' || import.meta.env?.DEV === true)
|
||||
const isDev = ref(
|
||||
process.env.NODE_ENV === 'development' ||
|
||||
(import.meta as any).env?.DEV === true ||
|
||||
window.location.hostname === 'localhost'
|
||||
)
|
||||
|
||||
// 面板状态
|
||||
const isCollapsed = ref(false)
|
||||
const isDragging = ref(false)
|
||||
const activeTab = ref('route')
|
||||
const activeTab = ref('backend') // 默认显示后端页面
|
||||
|
||||
// 面板位置
|
||||
const panelPosition = ref({
|
||||
|
||||
Reference in New Issue
Block a user