Compare commits

...

31 commits

Author SHA1 Message Date
e64295fa22 Merge branch 'main' of https://git.zhaozuohong.vip/mower-ng/mower-ng
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-08 00:39:24 +08:00
0e853f68a5 减慢填free的滑动速度 2024-12-08 00:39:09 +08:00
0dd1c28a2a 减少多余back回主页的发生 2024-12-08 00:33:28 +08:00
d7a949ad54 保全自动代理 2024-12-07 23:46:23 +08:00
ee7eda936a number匹配优化 2024-12-07 23:16:07 +08:00
c517e512a8 scrcpy kill_server
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-07 22:43:16 +08:00
36ed947ee4 add:保全代理元素与场景 2024-12-07 21:12:08 +08:00
bd3d83851e requirements.txt
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-07 20:15:08 +08:00
183898e5ea 修改swipe_update参数
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-07 20:11:39 +08:00
85c40dd426 允许不保存截图
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-07 19:43:15 +08:00
3c5c02e441 scrcpy启动应用
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-07 19:25:53 +08:00
ffc36ec2d2 av依赖 2024-12-07 19:18:06 +08:00
228270d9c5 前端收到截图前显示黑屏
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-07 19:03:41 +08:00
d07fb4f865 scrcpy virtual display 2024-12-07 19:00:44 +08:00
97b66d57ef 头像同名trap_去重
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-07 16:13:05 +08:00
7ec0694151 fix:第一段滑动参数写错
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-07 15:22:13 +08:00
7a06e924bc 读取作业适配旧type
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-07 15:09:03 +08:00
fe79e9ac1d rapidocr修正结果 2024-12-07 15:07:54 +08:00
7924e339ef skill_ready增加横向范围 2024-12-07 15:06:55 +08:00
429184dda7 get_pos限制范围 2024-12-07 15:06:06 +08:00
570bc19381 识别保全关卡改为ocr 2024-12-07 15:04:59 +08:00
904153b2ad 作业方向小写转大写 2024-12-07 15:04:24 +08:00
bbfdd005d5 保全战斗前增调装置适配新ui,去掉不必要的sleep 2024-12-07 15:03:34 +08:00
389c1834b4 前端显示截图
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-07 10:27:10 +08:00
28243b0e1f 读取conf时修正不对的Literal类型
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-06 22:01:57 +08:00
b27187cc57 swipe_update改进
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-06 19:08:27 +08:00
f59277a4ee mumuipc触控优化(选人不行,别用)
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-06 18:58:07 +08:00
30afa2f919 scrcpy内置0.1s延时
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-06 18:49:26 +08:00
0f36631d86 swipe_update修复
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-06 17:11:04 +08:00
d63942efa2 fix:判断战斗选人s滑动是否停下
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-06 01:39:40 +08:00
381a133a5a 右滑最后向上滑一下&fix:判断滑动是否结束
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-06 00:52:58 +08:00
57 changed files with 605 additions and 704 deletions

View file

@ -508,7 +508,10 @@ class Arknights数据处理器:
mask = full.copy() mask = full.copy()
name_list = [] name_list = []
i = 0 i = 0
trap_list = []
for filename in file_list: for filename in file_list:
if filename == "char_017_huang2.png":
continue
x = (i % col) * w x = (i % col) * w
y = (i // col) * h y = (i // col) * h
mx, my = sa(scope, (x, y)) mx, my = sa(scope, (x, y))
@ -517,6 +520,10 @@ class Arknights数据处理器:
# j: char_285_medic2 # j: char_285_medic2
# k: Lancet-2 # k: Lancet-2
if filename.startswith(j): if filename.startswith(j):
if filename.startswith("trap_"):
if k in trap_list:
break
trap_list.append(k)
img = loadimg(os.path.join(data_path, filename), True) img = loadimg(os.path.join(data_path, filename), True)
if img.shape != (h, w): if img.shape != (h, w):
img = cv2.resize(img, (w, h)) img = cv2.resize(img, (w, h))

View file

@ -615,6 +615,10 @@
"label": "SSS_CHOOSE_EC", "label": "SSS_CHOOSE_EC",
"comment": "选择定向元件" "comment": "选择定向元件"
}, },
"1019": {
"label": "SSS_ELIMI_AGENCY",
"comment": "保全扫荡确认"
},
"1101": { "1101": {
"label": "SF_ENTRANCE", "label": "SF_ENTRANCE",
"comment": "隐秘战线入口" "comment": "隐秘战线入口"

BIN
mower/resources/sss/ope/elimi_agency_on.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
mower/resources/sss/ope/prts.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
mower/resources/sss/ope/use.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -831,9 +831,9 @@ class BaseSchedulerSolver(SceneGraphSolver, BaseMixin):
if error_count > 3: if error_count > 3:
raise e raise e
error_count += 1 error_count += 1
self.back() self.cback(3)
continue continue
self.back() self.cback(3)
plan = self.op_data.plan plan = self.op_data.plan
fix_plan = {} fix_plan = {}
for key in plan: for key in plan:
@ -1946,7 +1946,9 @@ class BaseSchedulerSolver(SceneGraphSolver, BaseMixin):
else: else:
st = ret[-2][1][0] # 起点 st = ret[-2][1][0] # 起点
ed = ret[0][1][0] # 终点 ed = ret[0][1][0] # 终点
self.swipe_noinertia(st, (ed[0] - st[0], 0), interval=1) self.swipe_noinertia(
st, (ed[0] - st[0], 0), duration=400, interval=1
)
while self.find("confirm_blue"): while self.find("confirm_blue"):
self.tap("confirm_blue") self.tap("confirm_blue")

View file

@ -62,7 +62,7 @@ class BattleAgentChooseSolver(SceneGraphSolver):
f"tmp_swipe:{self.tmp_swipe[-1][1][0][0]}, {agents[-1][1][0][0]}" f"tmp_swipe:{self.tmp_swipe[-1][1][0][0]}, {agents[-1][1][0][0]}"
) )
if self.tmp_swipe[-1][0] == agents[-1][0]: if self.tmp_swipe[-1][0] == agents[-1][0]:
if abs(self.tmp_swipe[-1][1][0][0] - agents[-1][1][0][0]) > 30: if self.tmp_swipe[-1][1][0][0] != agents[-1][1][0][0]:
self.tmp_swipe = agents self.tmp_swipe = agents
return return
self.tmp_swipe = None self.tmp_swipe = None
@ -121,13 +121,14 @@ class BattleAgentChooseSolver(SceneGraphSolver):
# 右滑 # 右滑
self.before_swipe = agents self.before_swipe = agents
self.tmp_swipe = self.swipe_update( self.swipe_update(
[(1000, 540), (-2500, 0)], [(1000, 540), (-2500, 0)],
[600], [600],
self.interval, self.interval,
interval=self.interval, interval=self.interval,
func=operator_team_select,
) )
self.tmp_swipe = operator_team_select(config.recog.img)
logger.debug(f"右滑 {self.before_swipe},{self.tmp_swipe}") logger.debug(f"右滑 {self.before_swipe},{self.tmp_swipe}")
if self.tmp_swipe: if self.tmp_swipe:
if self.tmp_swipe[-1][0] == self.before_swipe[-1][0]: if self.tmp_swipe[-1][0] == self.before_swipe[-1][0]:

View file

@ -148,7 +148,7 @@ class FightMixin:
def toggle_speed(self): def toggle_speed(self):
target = 1 if self.speed == 2 else 2 target = 1 if self.speed == 2 else 2
logger.info(f"切换至{target}倍速") logger.info(f"切换至{target}倍速")
config.device.tap((1650, 80)) self.tap((1650, 80))
self.speed = target self.speed = target
self.complete_action() self.complete_action()
@ -243,7 +243,7 @@ class FightMixin:
"选中干员" "选中干员"
pos = self.calc.get_character_screen_pos(x, y, False, False) pos = self.calc.get_character_screen_pos(x, y, False, False)
pos = int(pos.x), int(pos.y) pos = int(pos.x), int(pos.y)
config.device.tap(pos) self.tap(pos)
def withdraw(self): def withdraw(self):
"撤下干员" "撤下干员"
@ -261,7 +261,7 @@ class FightMixin:
self.Bullet_Time = False self.Bullet_Time = False
pos = self.calc.get_with_draw_screen_pos(x, y) pos = self.calc.get_with_draw_screen_pos(x, y)
pos = int(pos.x), int(pos.y) pos = int(pos.x), int(pos.y)
config.device.tap(pos) self.tap(pos)
self.sleep(0.5) self.sleep(0.5)
self.clear_op() self.clear_op()
self.complete_action() self.complete_action()
@ -360,7 +360,7 @@ class FightMixin:
width = right - left width = right - left
height = bottom - top height = bottom - top
logger.debug(f"{width=} {height=}") logger.debug(f"{width=} {height=}")
return width < 900 and height < 850 return width < 950 and height < 850
except Exception as e: except Exception as e:
logger.exception(e) logger.exception(e)
return False return False
@ -400,7 +400,7 @@ class FightMixin:
skill_ready = loadres("fight/skill_ready", True) skill_ready = loadres("fight/skill_ready", True)
pos = self.calc.get_character_screen_pos(x, y, False, False) pos = self.calc.get_character_screen_pos(x, y, False, False)
pos = int(pos.x), int(pos.y) pos = int(pos.x), int(pos.y)
img = cropimg(config.recog.gray, sa(((-15, -168), (20, -118)), pos)) img = cropimg(config.recog.gray, sa(((-25, -168), (25, -118)), pos))
mask = np.ones_like(skill_ready, dtype=np.float32) mask = np.ones_like(skill_ready, dtype=np.float32)
mask[8:17, :] = 0.3 mask[8:17, :] = 0.3
result = cv2.matchTemplate( result = cv2.matchTemplate(
@ -457,7 +457,7 @@ class FightMixin:
else: else:
dir = (0, 400) dir = (0, 400)
dir = va(pos, dir) dir = va(pos, dir)
self.swipe_ext([start, pos], [config.conf.first_swipe_duration], 100, 0) self.swipe_ext([start, pos], [config.conf.first_swipe_duration], 100, 0.05)
if direction == "None": if direction == "None":
self.clear_op() self.clear_op()
self.location[(x, y)] = name self.location[(x, y)] = name

View file

@ -10,7 +10,7 @@ from mower.solvers.infra.riic_tag_choose import RIICTagChoose
from mower.utils import config from mower.utils import config
from mower.utils.character_recognize import operator_room_select from mower.utils.character_recognize import operator_room_select
from mower.utils.graph.utils import SceneGraphSolver from mower.utils.graph.utils import SceneGraphSolver
from mower.utils.image import cropimg from mower.utils.image import cropimg, diff_ratio
from mower.utils.log import logger from mower.utils.log import logger
from mower.utils.scene import Scene from mower.utils.scene import Scene
@ -25,6 +25,7 @@ class RIIC_ChooseSolver(SceneGraphSolver, BaseMixin):
agents (list): 选人名单 agents (list): 选人名单
wait_time (float, optional): 选人完成到按确定的时间 wait_time (float, optional): 选人完成到按确定的时间
""" """
logger.info(f"安排干员:{agents}")
self.agents = agents self.agents = agents
self.room = room self.room = room
self.wait_time = wait_time self.wait_time = wait_time
@ -40,6 +41,9 @@ class RIIC_ChooseSolver(SceneGraphSolver, BaseMixin):
self.tap_time = datetime.now() self.tap_time = datetime.now()
self.tmp_swipe = None self.tmp_swipe = None
self.recog_agents = None
self.before = None
self.solver_update_before_transition = True
self.choosed = [] self.choosed = []
logger.debug(f"待选名单:{self.agents}") logger.debug(f"待选名单:{self.agents}")
@ -60,38 +64,39 @@ class RIIC_ChooseSolver(SceneGraphSolver, BaseMixin):
""" """
self.agent = [self.agents_copy.pop(0), False, False] self.agent = [self.agents_copy.pop(0), False, False]
logger.info(f"开始选择干员:{self.agent[0]}") logger.info(f"开始选择干员:{self.agent[0]}")
else: else:
if self.wait_time > 0: if self.wait_time > 0:
self.sleep(self.check_wait_time()) self.sleep(self.check_wait_time())
self.success = True self.success = True
self.tap("confirm_blue") self.tap("confirm_blue")
return return
if self.before is not None:
self.sleep(0.1)
if diff_ratio(self.before, config.recog.gray):
logger.debug("滑动还在继续")
self.before = config.recog.gray
self.recog_agents = None
return
self.before = None
agents = operator_room_select(config.recog.img) if self.recog_agents is None:
agents_dict = dict(agents) self.recog_agents = dict(operator_room_select(config.recog.img))
if len(self.agents) > 1: if len(self.agents) > 1:
for i in agents_dict: for i in self.recog_agents:
if self.is_choosed(agents_dict[i]) and agents_dict[i][0][0] < 1600: if (
self.is_choosed(self.recog_agents[i])
and self.recog_agents[i][0][0] < 1600
):
if i not in self.agents and i not in self.choosed: if i not in self.agents and i not in self.choosed:
logger.info(f"存在错选 {i}") logger.info(f"存在错选 {i}")
self.tap("choose_agent/clear", interval=self.interval) self.tap("choose_agent/clear", interval=self.interval)
self.agents_copy = deepcopy(self.agents) self.agents_copy = deepcopy(self.agents)
self.choosed = [] self.choosed = []
self.recog_agents = None
self.agent = None self.agent = None
return return
if self.tmp_swipe:
logger.debug(
f"tmp_swipe:{self.tmp_swipe[-1][1][0][0]}, {agents[-1][1][0][0]}"
)
if self.tmp_swipe[-1][0] == agents[-1][0]:
if abs(self.tmp_swipe[-1][1][0][0] - agents[-1][1][0][0]) > 30:
self.tmp_swipe = agents
return
self.tmp_swipe = None
agent_name = self.agent[0] agent_name = self.agent[0]
if agent_name == "Free": if agent_name == "Free":
@ -99,20 +104,28 @@ class RIIC_ChooseSolver(SceneGraphSolver, BaseMixin):
self.agent = None self.agent = None
return return
if agent_name in agents_dict.keys(): if agent_name in self.recog_agents.keys():
is_choosed = self.is_choosed(agents_dict[agent_name]) is_choosed = self.is_choosed(self.recog_agents[agent_name])
logger.debug(f"{agent_name} 是否被选上:{is_choosed}")
if is_choosed: if is_choosed:
logger.info(f"{agent_name}选择完成") logger.info(f"{agent_name}选择完成")
self.recog_agents = None
self.choosed.append(agent_name) self.choosed.append(agent_name)
self.agent = None self.agent = None
else: else:
if agents_dict[agent_name][0][0] > 1650: if self.recog_agents[agent_name][0][0] > 1650:
self.swipe_noinertia((1000, 540), (-500, 0), interval=0.5) logger.debug(f"滑动调整位置 {self.recog_agents[agent_name]}")
self.swipe_update(
[(700, 770), (400, 770), (400, 500)],
[200, 200],
up_wait=200,
interval=0.2,
)
self.recog_agents = None
return return
logger.debug(f"tap {agent_name} ") logger.debug(f"tap {agent_name} ")
self.ctap(agents_dict[agent_name], 2, self.interval, agent_name) self.ctap(self.recog_agents[agent_name], 5, self.interval, agent_name)
self.recog_agents = None
return return
logger.debug(f"选tag和左滑 {self.agent}") logger.debug(f"选tag和左滑 {self.agent}")
@ -123,39 +136,42 @@ class RIIC_ChooseSolver(SceneGraphSolver, BaseMixin):
if RIICTagChoose().run(tag): if RIICTagChoose().run(tag):
self.agent[1] = True self.agent[1] = True
self.recog_agents = None
return return
if self.agent[2] is False: if self.agent[2] is False:
if self.tmp_left is None: tmp_recog = self.swipe_update(
self.tmp_left = list(agents_dict.keys())[0] [(700, 770), (1600, 770), (1600, 500)],
self.swipe_noinertia((1000, 540), (300, 0), interval=0.5) [200, 200],
return up_wait=200,
elif self.tmp_left != list(agents_dict.keys())[0]: interval=0.2,
self.swipe_noinertia((1000, 540), (1000, 0), interval=0.5) func=operator_room_select,
self.tmp_left = list(agents_dict.keys())[0] )
return if tmp_recog[0][0] == list(self.recog_agents.keys())[0]:
self.agent[2] = True self.agent[2] = True
self.recog_agents = None
return return
# 右滑 # 右滑
self.before_swipe = agents self.recog_agents = dict(
self.tmp_swipe = self.swipe_update( self.swipe_update(
[(1000, 540), (-2500, 0)], [(1600, 770), (600, 770), (600, 900)],
[600], [300, 500],
self.interval, up_wait=200,
interval=self.interval, interval=0.2,
func=operator_room_select, func=operator_room_select,
)
) )
logger.debug(f"右滑 {self.before_swipe},{self.tmp_swipe}") tmp_img = config.recog.gray
if self.tmp_swipe: config.recog.update()
if self.tmp_swipe[-1][0] == self.before_swipe[-1][0]: if diff_ratio(tmp_img, config.recog.gray):
if self.tmp_swipe[-1][1][0][0] == self.before_swipe[-1][1][0][0]: if agent_name not in self.recog_agents.keys():
logger.error(RuntimeError("滑动失败")) logger.info(f"缺少:{agent_name}")
return True return True
else:
self.tmp_swipe[-1][1][0][0] != self.before_swipe[-1][1][0][0] self.before = config.recog.gray
raise RuntimeError(f"缺少干员 {self.agent[0]}")
def is_choosed(self, scope) -> bool: def is_choosed(self, scope) -> bool:
# logger.info(scope)
up_pt = cropimg( up_pt = cropimg(
config.recog.img, config.recog.img,
[ [
@ -171,8 +187,9 @@ class RIIC_ChooseSolver(SceneGraphSolver, BaseMixin):
[scope[0][0] + 1, scope[1][1] + 213], [scope[0][0] + 1, scope[1][1] + 213],
], ],
)[0][0][0] )[0][0][0]
logger.debug(f"is_choosed: {up_pt}{down_pt}")
if (up_pt < 50) and down_pt < 50: logger.debug(f"is_choosed: {up_pt},{down_pt}")
if up_pt < 50 and down_pt < 50:
return True return True
return False return False

View file

@ -102,7 +102,7 @@ class EnterRoomSolver(SceneGraphSolver, BaseMixin):
super().run() super().run()
def timeout(self) -> bool: def timeout(self) -> bool:
return datetime.now() > self.start_time + timedelta(seconds=3) return datetime.now() > self.start_time + timedelta(seconds=5)
def bug_timeout(self) -> bool: def bug_timeout(self) -> bool:
return datetime.now() > self.avoid_bug_start_time + timedelta(seconds=60) return datetime.now() > self.avoid_bug_start_time + timedelta(seconds=60)
@ -147,8 +147,8 @@ class EnterRoomSolver(SceneGraphSolver, BaseMixin):
elif scene in [Scene.CTRLCENTER_ASSISTANT, Scene.INFRA_DETAILS]: elif scene in [Scene.CTRLCENTER_ASSISTANT, Scene.INFRA_DETAILS]:
if self.detect_room() == self.room: if self.detect_room() == self.room:
if not self.detail: if not self.detail and self.find("arrange_check_in_on"):
self.tap((960, 540), interval=0) self.tap((960, 540))
return True return True
if self.find("room_detail"): if self.find("room_detail"):
return True return True

View file

@ -65,9 +65,8 @@ class GetAgentFromRoomSolver(SceneGraphSolver, BaseMixin):
img = cv2.resize(img, None, None, scale, scale) img = cv2.resize(img, None, None, scale, scale)
img = thres2(img, thres) img = thres2(img, thres)
img = cv2.bitwise_not(img) img = cv2.bitwise_not(img)
return ( return config.recog.num.number_int(
config.recog.num.number_int("riic_base", img=img, target_range=range(1, 6)) "riic_base", img=img, target_range=range(1, 6)
+ 1
) )
@staticmethod @staticmethod

View file

@ -83,7 +83,7 @@ class ReclamationAlgorithm(SceneGraphSolver):
def tap_loop(self, pos): def tap_loop(self, pos):
while not self.event.is_set(): while not self.event.is_set():
config.device.tap(pos) self.tap(pos)
def fast_tap(self, pos): def fast_tap(self, pos):
self.event.clear() self.event.clear()

View file

@ -1,18 +1,17 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
import cv2
from mower.utils import config from mower.utils import config
from mower.utils.email import send_message from mower.utils.email import send_message
from mower.utils.generate_image import generate_image
from mower.utils.graph import SceneGraphSolver from mower.utils.graph import SceneGraphSolver
from mower.utils.image import cropimg from mower.utils.image import cropimg
from mower.utils.log import logger from mower.utils.log import logger
from mower.utils.rapidocr import ocr_rec
from mower.utils.recognize import Scene from mower.utils.recognize import Scene
from .sss_choose import SSSChooseSolver from .sss_choose import SSSChooseSolver
from .sss_fight import SSSFightSolver from .sss_fight import SSSFightSolver
from .sss_navi import SSSNaviSolver from .sss_navi import SSSNaviSolver
from .sss_ope import SSSOpeSolver
from .utils import is_full from .utils import is_full
@ -41,16 +40,9 @@ class SSSSolver(SceneGraphSolver):
self.stages[stage_name] = stage self.stages[stage_name] = stage
def detect_stage(self): def detect_stage(self):
for stage in self.stages: img = cropimg(config.recog.img, ((180, 400), (420, 480)))
stage_name_size = 40 if len(stage) < 6 else 34 res = ocr_rec(img)
res = generate_image(stage, stage_name_size) return res
img = cropimg(config.recog.gray, ((180, 400), (420, 480)))
result = cv2.matchTemplate(img, res, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
logger.debug(f"stage:{stage},max_val:{max_val}")
if max_val > 0.85:
return stage
return None
def transition(self): def transition(self):
if self.deadline and self.deadline < datetime.now(): if self.deadline and self.deadline < datetime.now():
@ -76,7 +68,13 @@ class SSSSolver(SceneGraphSolver):
send_message("保全模组条与仪已刷满", level="WARNING") send_message("保全模组条与仪已刷满", level="WARNING")
self.full = True self.full = True
return True return True
elif (
scene == Scene.SSS_START
and config.conf.sss.finish_while_full
and self.find("sss/ope/prts")
):
self.full = SSSOpeSolver().run()
return self.full
elif scene == Scene.SSS_DROP_AGENT_BEFORE_FIGHT: elif scene == Scene.SSS_DROP_AGENT_BEFORE_FIGHT:
self.scene_graph_step(Scene.SSS_DEPLOY) self.scene_graph_step(Scene.SSS_DEPLOY)

View file

@ -10,6 +10,7 @@ from mower.utils.generate_image import generate_image
from mower.utils.graph import SceneGraphSolver from mower.utils.graph import SceneGraphSolver
from mower.utils.image import cropimg, loadres, thres2 from mower.utils.image import cropimg, loadres, thres2
from mower.utils.log import logger from mower.utils.log import logger
from mower.utils.rapidocr import ocr_rec
from mower.utils.recognize import Scene from mower.utils.recognize import Scene
from mower.utils.vector import ss, va from mower.utils.vector import ss, va
@ -109,12 +110,10 @@ class SSSDROPSolver(SceneGraphSolver):
for drop in self.drops: for drop in self.drops:
if drop in opers: if drop in opers:
self.tap(opers[drop]) self.tap(opers[drop])
self.sleep(0.5)
self.choose = True self.choose = True
return return
if len(opers): if len(opers):
self.tap(opers.popitem()[1]) self.tap(opers.popitem()[1])
self.sleep(0.5)
self.choose = True self.choose = True
return return
@ -123,13 +122,11 @@ class SSSDROPSolver(SceneGraphSolver):
if drop not in agent: if drop not in agent:
if pos := self.find_EC(drop, 29, ((510, 700), (1480, 770))): if pos := self.find_EC(drop, 29, ((510, 700), (1480, 770))):
self.tap(pos) self.tap(pos)
self.sleep(0.5)
self.tap((1750, 550)) self.tap((1750, 550))
return return
else: else:
if pos := self.find_PR_in_fight(drop, ((468, 735), (1321, 797))): if pos := self.find_PR_in_fight(drop, ((468, 735), (1321, 797))):
self.tap(pos) self.tap(pos)
self.sleep(0.5)
self.tap((1750, 550)) self.tap((1750, 550))
return return
self.tap("sss/abandon") self.tap("sss/abandon")
@ -142,13 +139,15 @@ class SSSDROPSolver(SceneGraphSolver):
self.tap((1794, 900)) self.tap((1794, 900))
return return
else: else:
ec_pos = [((470, 400), (800, 450)), ((1200, 400), (1530, 450))]
res = {}
for pos in ec_pos:
img = cropimg(config.recog.img, pos)
res[ocr_rec(img)] = pos
for drop in self.drops: for drop in self.drops:
if drop not in agent: if drop in res:
if pos := self.find_EC(drop, 30, ((640, 630), (1280, 700))): self.tap(res[drop])
self.tap(pos) self.choose = True
self.sleep(0.5)
self.choose = True
return
elif scene == Scene.SSS_ABANDON_DROP_IN_FIGHT: elif scene == Scene.SSS_ABANDON_DROP_IN_FIGHT:
self.scene_graph_step(Scene.OPERATOR_FIGHT) self.scene_graph_step(Scene.OPERATOR_FIGHT)

View file

@ -77,6 +77,9 @@ class SSSNaviSolver(SceneGraphSolver):
elif self.mode == "ex" and self.find("sss/switch_to_ex"): elif self.mode == "ex" and self.find("sss/switch_to_ex"):
self.tap("sss/switch_to_ex") self.tap("sss/switch_to_ex")
return return
if config.conf.sss.finish_while_full and self.find("sss/ope/prts"):
return True
self.tap((1555, 966)) self.tap((1555, 966))
elif scene == Scene.SSS_CHOOSE_EC: elif scene == Scene.SSS_CHOOSE_EC:
for scope in ec_pos: for scope in ec_pos:

View file

@ -0,0 +1,48 @@
from mower.utils import config
from mower.utils.graph import SceneGraphSolver
from mower.utils.recognize import Scene
from .utils import is_full
class SSSOpeSolver(SceneGraphSolver):
solver_name = "保全代理"
def run(self) -> bool:
self.success = False # 是否刷满
self.check = False # 是否可代理层数小于设置要求
super().run()
return self.success
def transition(self):
if (scene := self.scene()) == Scene.SSS_START:
if self.find("sss/ope/prts") and not self.check:
self.tap("sss/ope/prts")
return
elif self.find("sss/ope/elimi_agency_on") and self.check:
self.tap("sss/ope/elimi_agency_on")
return
self.tap((1555, 966))
elif scene in [Scene.SSS_EC, Scene.SSS_EC_EX] and self.check:
return True
elif scene == Scene.SSS_ELIMI_AGENCY:
if is_full():
self.success = True
return True
if (
config.recog.num.number_int(
"riic_base",
((1750, 50), (1850, 150)),
50,
120,
target_range=range(1, 7),
)
< config.conf.sss.ope_limit_stage
):
self.scene_graph_step(Scene.SSS_START)
self.check = True
return
self.tap("sss/ope/use")
else:
self.scene_graph_step(Scene.SSS_START)

View file

@ -9,8 +9,8 @@ def number(scope: tp.Scope, height: int, thres: int) -> int:
def is_full() -> bool: def is_full() -> bool:
"判断模块增补仪和条是否刷满" "判断模块增补仪和条是否刷满"
if number(((150, 975), (300, 1030)), 50, 120) != 60: if number(((150, 975), (300, 1030)), 50, 100) != 60:
return False return False
if number(((530, 975), (680, 1030)), 50, 120) != 24: if number(((530, 975), (680, 1030)), 50, 100) != 24:
return False return False
return True return True

BIN
mower/static/avatar.pkl (Stored with Git LFS)

Binary file not shown.

View file

@ -110,7 +110,7 @@ operators = {}
# 日志 # 日志
log_queue = Queue() log_queue = Queue()
wh = None sc_queue = Queue()
screenshot_time: datetime = datetime.now() - timedelta( screenshot_time: datetime = datetime.now() - timedelta(
milliseconds=conf.screenshot_interval milliseconds=conf.screenshot_interval

View file

@ -1,4 +1,4 @@
from typing import Literal from typing import Literal, get_args, get_origin
from pydantic import BaseModel, model_validator from pydantic import BaseModel, model_validator
from pydantic_core import PydanticUndefined from pydantic_core import PydanticUndefined
@ -14,6 +14,30 @@ class ConfModel(BaseModel):
data[name] = field.annotation() data[name] = field.annotation()
else: else:
data[name] = field.default data[name] = field.default
else:
value = data[name]
expected_type = field.annotation
# 处理嵌套的 BaseModel
if isinstance(field.annotation, type) and issubclass(
field.annotation, BaseModel
):
if not isinstance(value, dict): # 确保嵌套类型为字典
value = {}
# 递归调用嵌套模型的验证器
data[name] = field.annotation(**value)
# 检查 Literal 类型并修正
elif get_origin(expected_type) is Literal:
valid_literals = get_args(expected_type)
if value not in valid_literals:
# 修正为默认值
data[name] = (
field.default
if field.default is not PydanticUndefined
else None
)
return data return data
@ -197,10 +221,12 @@ class LongTaskPart(ConfModel):
class SSSConf(ConfModel): class SSSConf(ConfModel):
choose_agent: bool = True choose_agent: bool = True
"自动编队" "自动编队"
mode: str = "normal" mode: Literal["normal", "ex"] = "normal"
"难度:正常为normal,应急为ex" "难度:正常为normal,应急为ex"
finish_while_full: bool = True finish_while_full: bool = True
"模组刷满时直接结束" "模组刷满时直接结束"
ope_limit_stage: int = 6
"使用代理卡最低层数要求"
maa_rg_enable: int = 0 maa_rg_enable: int = 0
"大型任务" "大型任务"
@ -385,7 +411,7 @@ class EmulatorPart(ConfModel):
"截图方案" "截图方案"
control_strategy: Literal["scrcpy", "mumuipc"] = "scrcpy" control_strategy: Literal["scrcpy", "mumuipc"] = "scrcpy"
"触控方案" "触控方案"
app_control_strategy: Literal["adb", "mumumanager"] = "adb" app_control_strategy: Literal["adb", "mumumanager", "scrcpy"] = "adb"
"应用控制方案" "应用控制方案"

View file

@ -46,6 +46,7 @@ class Action(BaseModel):
"MoveCamera", "MoveCamera",
"调配干员", "调配干员",
"CheckIfStartOver", "CheckIfStartOver",
"GetDrops",
] = "Deploy" ] = "Deploy"
name: Optional[str] = None name: Optional[str] = None
costs: Optional[int] = None costs: Optional[int] = None

View file

@ -69,11 +69,6 @@ class Device:
logger.debug(keycode) logger.debug(keycode)
self.control.send_keyevent(keycode) self.control.send_keyevent(keycode)
def send_text(self, text: str) -> None:
"""send a text"""
logger.debug(repr(text))
self.app_control.send_text(text)
def screencap(self) -> bytes: def screencap(self) -> bytes:
start_time = datetime.now() start_time = datetime.now()
if config.conf.screencap_strategy != "scrcpy": if config.conf.screencap_strategy != "scrcpy":
@ -105,14 +100,6 @@ class Device:
save_screenshot(img) save_screenshot(img)
return img return img
def current_focus(self) -> str:
"""detect current focus app"""
return self.app_control.current_focus()
def display_frames(self) -> tuple[int, int, int]:
"""get display frames if in compatibility mode"""
return self.app_control.display_frames()
def tap(self, point: tuple[int, int]) -> None: def tap(self, point: tuple[int, int]) -> None:
"""tap""" """tap"""
logger.debug(point) logger.debug(point)
@ -150,7 +137,7 @@ class Device:
Any: func的返回值 Any: func的返回值
""" """
logger.debug(f"{points=} {durations=} {update=} {interval=} {func=}") logger.debug(f"{points=} {durations=} {update=} {interval=} {func=}")
self.control.swipe_ext(points, durations, update, interval, func) return self.control.swipe_ext(points, durations, update, interval, func)
def check_current_focus(self) -> bool: def check_current_focus(self) -> bool:
"""check if the application is in the foreground""" """check if the application is in the foreground"""

View file

@ -221,29 +221,12 @@ class ADB:
"am start -a android.intent.action.MAIN -c android.intent.category.HOME" "am start -a android.intent.action.MAIN -c android.intent.category.HOME"
) )
def send_text(self, text: str) -> None:
"""send a text"""
text = text.replace('"', '\\"')
command = f'input text "{text}"'
self.adb_shell(command)
def current_focus(self) -> str: def current_focus(self) -> str:
"""detect current focus app""" """detect current focus app"""
command = "dumpsys window | grep mCurrentFocus" command = "dumpsys window | grep mCurrentFocus"
line = self.adb_shell(command) line = self.adb_shell(command)
return line.strip()[:-1].split(" ")[-1] return line.strip()[:-1].split(" ")[-1]
def display_frames(self) -> tuple[int, int, int]:
"""get display frames if in compatibility mode"""
if not config.MNT_COMPATIBILITY_MODE:
return None
command = "dumpsys window | grep DisplayFrames"
line = self.adb_shell(command)
""" eg. DisplayFrames w=1920 h=1080 r=3 """
res = line.strip().replace("=", " ").split(" ")
return int(res[2]), int(res[4]), int(res[6])
def check_current_focus(self) -> bool: def check_current_focus(self) -> bool:
"""check if the application is in the foreground""" """check if the application is in the foreground"""
update = False update = False

View file

@ -10,10 +10,12 @@ import numpy as np
from mower.utils import config from mower.utils import config
from mower.utils import typealias as tp from mower.utils import typealias as tp
from mower.utils.csleep import MowerExit from mower.utils.csleep import MowerExit
from mower.utils.device import swipe_update
from mower.utils.device.emulator import restart_emulator from mower.utils.device.emulator import restart_emulator
from mower.utils.device.exception import EmulatorError, GameError from mower.utils.device.exception import EmulatorError, GameError
from mower.utils.device.method.mumumanager import MuMuManager from mower.utils.device.method.mumumanager import MuMuManager
from mower.utils.log import logger from mower.utils.log import logger
from mower.utils.vector import sm, va
class NemuIpcIncompatible(Exception): class NemuIpcIncompatible(Exception):
@ -234,7 +236,7 @@ class MuMu12IPC:
def finger_touch_down(self, finger_id: int, x: int, y: int): def finger_touch_down(self, finger_id: int, x: int, y: int):
self.check_status() self.check_status()
result = self.external_renderer.nemu_input_event_finger_touch_down( result = self.external_renderer.nemu_input_event_finger_touch_down(
self.connection, self.display_id, finger_id, x, y self.connection, self.display_id, finger_id, int(1080 - y), int(x)
) )
if result != 0: if result != 0:
self.connection = 0 self.connection = 0
@ -300,42 +302,36 @@ class MuMu12IPC:
interval (float): 滑动完成后的等待时间单位为秒默认 0 interval (float): 滑动完成后的等待时间单位为秒默认 0
func (Callable[[np.ndarray], Any]): 截图后处理的函数默认空函数 func (Callable[[np.ndarray], Any]): 截图后处理的函数默认空函数
""" """
frame_time = 1 / 30 # 模拟帧率为 30 FPS frame_time = 1 / 30
steps = max(int(duration / frame_time), 1) # 计算滑动的总步数
time_per_step = duration / steps # 每步所需时间
# 可选截图功能 start_time = time.perf_counter()
if update: fall and self.touch_down(x0, y0)
initial_image = self.capture_display() # 截图
thread = threading.Thread(target=func, args=(initial_image,)) if update and config.recog:
thread = threading.Thread(target=swipe_update.start, args=(func,))
thread.start() thread.start()
# 按下起点 if (down_time := time.perf_counter()) < start_time + frame_time:
if fall: time.sleep(start_time + frame_time - down_time)
self.touch_down(x0, y0) down_time = start_time + frame_time
# 滑动过程 while (progress := (time.perf_counter() - down_time) / duration) <= 1:
for step in range(steps): x, y = va(sm(1 - progress, (x0, y0)), sm(progress, (x1, y1)))
progress = (step + 1) / steps start_time = time.perf_counter()
x = int(x0 + (x1 - x0) * progress)
y = int(y0 + (y1 - y0) * progress)
# 确保每步保持固定帧时间
step_start = time.perf_counter()
self.touch_down(x, y) self.touch_down(x, y)
elapsed = time.perf_counter() - step_start if (move_time := time.perf_counter() - start_time) < frame_time:
if elapsed < time_per_step: time.sleep(frame_time - move_time)
time.sleep(time_per_step - elapsed) self.touch_down(x1, y1)
# 到达终点 lift and self.touch_up()
if lift:
self.touch_up()
# 等待截图线程完成 if update and config.recog:
if update: start_time = time.perf_counter()
thread.join() thread.join()
if (stop_time := time.perf_counter()) < start_time + interval:
time.sleep(start_time + interval - stop_time)
return swipe_update.result
# 滑动完成后的等待时间
if interval > 0: if interval > 0:
time.sleep(interval) time.sleep(interval)

View file

@ -1,329 +1,12 @@
"""
This module includes all consts used in this project
"""
# Action # Action
ACTION_DOWN = 0 ACTION_DOWN = 0
ACTION_UP = 1 ACTION_UP = 1
ACTION_MOVE = 2 ACTION_MOVE = 2
# KeyCode # KeyCode
KEYCODE_UNKNOWN = 0
KEYCODE_SOFT_LEFT = 1
KEYCODE_SOFT_RIGHT = 2
KEYCODE_HOME = 3
KEYCODE_BACK = 4 KEYCODE_BACK = 4
KEYCODE_CALL = 5
KEYCODE_ENDCALL = 6
KEYCODE_0 = 7
KEYCODE_1 = 8
KEYCODE_2 = 9
KEYCODE_3 = 10
KEYCODE_4 = 11
KEYCODE_5 = 12
KEYCODE_6 = 13
KEYCODE_7 = 14
KEYCODE_8 = 15
KEYCODE_9 = 16
KEYCODE_STAR = 17
KEYCODE_POUND = 18
KEYCODE_DPAD_UP = 19
KEYCODE_DPAD_DOWN = 20
KEYCODE_DPAD_LEFT = 21
KEYCODE_DPAD_RIGHT = 22
KEYCODE_DPAD_CENTER = 23
KEYCODE_VOLUME_UP = 24
KEYCODE_VOLUME_DOWN = 25
KEYCODE_POWER = 26
KEYCODE_CAMERA = 27
KEYCODE_CLEAR = 28
KEYCODE_A = 29
KEYCODE_B = 30
KEYCODE_C = 31
KEYCODE_D = 32
KEYCODE_E = 33
KEYCODE_F = 34
KEYCODE_G = 35
KEYCODE_H = 36
KEYCODE_I = 37
KEYCODE_J = 38
KEYCODE_K = 39
KEYCODE_L = 40
KEYCODE_M = 41
KEYCODE_N = 42
KEYCODE_O = 43
KEYCODE_P = 44
KEYCODE_Q = 45
KEYCODE_R = 46
KEYCODE_S = 47
KEYCODE_T = 48
KEYCODE_U = 49
KEYCODE_V = 50
KEYCODE_W = 51
KEYCODE_X = 52
KEYCODE_Y = 53
KEYCODE_Z = 54
KEYCODE_COMMA = 55
KEYCODE_PERIOD = 56
KEYCODE_ALT_LEFT = 57
KEYCODE_ALT_RIGHT = 58
KEYCODE_SHIFT_LEFT = 59
KEYCODE_SHIFT_RIGHT = 60
KEYCODE_TAB = 61
KEYCODE_SPACE = 62
KEYCODE_SYM = 63
KEYCODE_EXPLORER = 64
KEYCODE_ENVELOPE = 65
KEYCODE_ENTER = 66
KEYCODE_DEL = 67
KEYCODE_GRAVE = 68
KEYCODE_MINUS = 69
KEYCODE_EQUALS = 70
KEYCODE_LEFT_BRACKET = 71
KEYCODE_RIGHT_BRACKET = 72
KEYCODE_BACKSLASH = 73
KEYCODE_SEMICOLON = 74
KEYCODE_APOSTROPHE = 75
KEYCODE_SLASH = 76
KEYCODE_AT = 77
KEYCODE_NUM = 78
KEYCODE_HEADSETHOOK = 79
KEYCODE_PLUS = 81
KEYCODE_MENU = 82
KEYCODE_NOTIFICATION = 83
KEYCODE_SEARCH = 84
KEYCODE_MEDIA_PLAY_PAUSE = 85
KEYCODE_MEDIA_STOP = 86
KEYCODE_MEDIA_NEXT = 87
KEYCODE_MEDIA_PREVIOUS = 88
KEYCODE_MEDIA_REWIND = 89
KEYCODE_MEDIA_FAST_FORWARD = 90
KEYCODE_MUTE = 91
KEYCODE_PAGE_UP = 92
KEYCODE_PAGE_DOWN = 93
KEYCODE_BUTTON_A = 96
KEYCODE_BUTTON_B = 97
KEYCODE_BUTTON_C = 98
KEYCODE_BUTTON_X = 99
KEYCODE_BUTTON_Y = 100
KEYCODE_BUTTON_Z = 101
KEYCODE_BUTTON_L1 = 102
KEYCODE_BUTTON_R1 = 103
KEYCODE_BUTTON_L2 = 104
KEYCODE_BUTTON_R2 = 105
KEYCODE_BUTTON_THUMBL = 106
KEYCODE_BUTTON_THUMBR = 107
KEYCODE_BUTTON_START = 108
KEYCODE_BUTTON_SELECT = 109
KEYCODE_BUTTON_MODE = 110
KEYCODE_ESCAPE = 111
KEYCODE_FORWARD_DEL = 112
KEYCODE_CTRL_LEFT = 113
KEYCODE_CTRL_RIGHT = 114
KEYCODE_CAPS_LOCK = 115
KEYCODE_SCROLL_LOCK = 116
KEYCODE_META_LEFT = 117
KEYCODE_META_RIGHT = 118
KEYCODE_FUNCTION = 119
KEYCODE_SYSRQ = 120
KEYCODE_BREAK = 121
KEYCODE_MOVE_HOME = 122
KEYCODE_MOVE_END = 123
KEYCODE_INSERT = 124
KEYCODE_FORWARD = 125
KEYCODE_MEDIA_PLAY = 126
KEYCODE_MEDIA_PAUSE = 127
KEYCODE_MEDIA_CLOSE = 128
KEYCODE_MEDIA_EJECT = 129
KEYCODE_MEDIA_RECORD = 130
KEYCODE_F1 = 131
KEYCODE_F2 = 132
KEYCODE_F3 = 133
KEYCODE_F4 = 134
KEYCODE_F5 = 135
KEYCODE_F6 = 136
KEYCODE_F7 = 137
KEYCODE_F8 = 138
KEYCODE_F9 = 139
KEYCODE_F10 = 140
KEYCODE_F11 = 141
KEYCODE_F12 = 142
KEYCODE_NUM_LOCK = 143
KEYCODE_NUMPAD_0 = 144
KEYCODE_NUMPAD_1 = 145
KEYCODE_NUMPAD_2 = 146
KEYCODE_NUMPAD_3 = 147
KEYCODE_NUMPAD_4 = 148
KEYCODE_NUMPAD_5 = 149
KEYCODE_NUMPAD_6 = 150
KEYCODE_NUMPAD_7 = 151
KEYCODE_NUMPAD_8 = 152
KEYCODE_NUMPAD_9 = 153
KEYCODE_NUMPAD_DIVIDE = 154
KEYCODE_NUMPAD_MULTIPLY = 155
KEYCODE_NUMPAD_SUBTRACT = 156
KEYCODE_NUMPAD_ADD = 157
KEYCODE_NUMPAD_DOT = 158
KEYCODE_NUMPAD_COMMA = 159
KEYCODE_NUMPAD_ENTER = 160
KEYCODE_NUMPAD_EQUALS = 161
KEYCODE_NUMPAD_LEFT_PAREN = 162
KEYCODE_NUMPAD_RIGHT_PAREN = 163
KEYCODE_VOLUME_MUTE = 164
KEYCODE_INFO = 165
KEYCODE_CHANNEL_UP = 166
KEYCODE_CHANNEL_DOWN = 167
KEYCODE_ZOOM_IN = 168
KEYCODE_ZOOM_OUT = 169
KEYCODE_TV = 170
KEYCODE_WINDOW = 171
KEYCODE_GUIDE = 172
KEYCODE_DVR = 173
KEYCODE_BOOKMARK = 174
KEYCODE_CAPTIONS = 175
KEYCODE_SETTINGS = 176
KEYCODE_TV_POWER = 177
KEYCODE_TV_INPUT = 178
KEYCODE_STB_POWER = 179
KEYCODE_STB_INPUT = 180
KEYCODE_AVR_POWER = 181
KEYCODE_AVR_INPUT = 182
KEYCODE_PROG_RED = 183
KEYCODE_PROG_GREEN = 184
KEYCODE_PROG_YELLOW = 185
KEYCODE_PROG_BLUE = 186
KEYCODE_APP_SWITCH = 187
KEYCODE_BUTTON_1 = 188
KEYCODE_BUTTON_2 = 189
KEYCODE_BUTTON_3 = 190
KEYCODE_BUTTON_4 = 191
KEYCODE_BUTTON_5 = 192
KEYCODE_BUTTON_6 = 193
KEYCODE_BUTTON_7 = 194
KEYCODE_BUTTON_8 = 195
KEYCODE_BUTTON_9 = 196
KEYCODE_BUTTON_10 = 197
KEYCODE_BUTTON_11 = 198
KEYCODE_BUTTON_12 = 199
KEYCODE_BUTTON_13 = 200
KEYCODE_BUTTON_14 = 201
KEYCODE_BUTTON_15 = 202
KEYCODE_BUTTON_16 = 203
KEYCODE_LANGUAGE_SWITCH = 204
KEYCODE_MANNER_MODE = 205
KEYCODE_3D_MODE = 206
KEYCODE_CONTACTS = 207
KEYCODE_CALENDAR = 208
KEYCODE_MUSIC = 209
KEYCODE_CALCULATOR = 210
KEYCODE_ZENKAKU_HANKAKU = 211
KEYCODE_EISU = 212
KEYCODE_MUHENKAN = 213
KEYCODE_HENKAN = 214
KEYCODE_KATAKANA_HIRAGANA = 215
KEYCODE_YEN = 216
KEYCODE_RO = 217
KEYCODE_KANA = 218
KEYCODE_ASSIST = 219
KEYCODE_BRIGHTNESS_DOWN = 220
KEYCODE_BRIGHTNESS_UP = 221
KEYCODE_MEDIA_AUDIO_TRACK = 222
KEYCODE_SLEEP = 223
KEYCODE_WAKEUP = 224
KEYCODE_PAIRING = 225
KEYCODE_MEDIA_TOP_MENU = 226
KEYCODE_11 = 227
KEYCODE_12 = 228
KEYCODE_LAST_CHANNEL = 229
KEYCODE_TV_DATA_SERVICE = 230
KEYCODE_VOICE_ASSIST = 231
KEYCODE_TV_RADIO_SERVICE = 232
KEYCODE_TV_TELETEXT = 233
KEYCODE_TV_NUMBER_ENTRY = 234
KEYCODE_TV_TERRESTRIAL_ANALOG = 235
KEYCODE_TV_TERRESTRIAL_DIGITAL = 236
KEYCODE_TV_SATELLITE = 237
KEYCODE_TV_SATELLITE_BS = 238
KEYCODE_TV_SATELLITE_CS = 239
KEYCODE_TV_SATELLITE_SERVICE = 240
KEYCODE_TV_NETWORK = 241
KEYCODE_TV_ANTENNA_CABLE = 242
KEYCODE_TV_INPUT_HDMI_1 = 243
KEYCODE_TV_INPUT_HDMI_2 = 244
KEYCODE_TV_INPUT_HDMI_3 = 245
KEYCODE_TV_INPUT_HDMI_4 = 246
KEYCODE_TV_INPUT_COMPOSITE_1 = 247
KEYCODE_TV_INPUT_COMPOSITE_2 = 248
KEYCODE_TV_INPUT_COMPONENT_1 = 249
KEYCODE_TV_INPUT_COMPONENT_2 = 250
KEYCODE_TV_INPUT_VGA_1 = 251
KEYCODE_TV_AUDIO_DESCRIPTION = 252
KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253
KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254
KEYCODE_TV_ZOOM_MODE = 255
KEYCODE_TV_CONTENTS_MENU = 256
KEYCODE_TV_MEDIA_CONTEXT_MENU = 257
KEYCODE_TV_TIMER_PROGRAMMING = 258
KEYCODE_HELP = 259
KEYCODE_NAVIGATE_PREVIOUS = 260
KEYCODE_NAVIGATE_NEXT = 261
KEYCODE_NAVIGATE_IN = 262
KEYCODE_NAVIGATE_OUT = 263
KEYCODE_STEM_PRIMARY = 264
KEYCODE_STEM_1 = 265
KEYCODE_STEM_2 = 266
KEYCODE_STEM_3 = 267
KEYCODE_DPAD_UP_LEFT = 268
KEYCODE_DPAD_DOWN_LEFT = 269
KEYCODE_DPAD_UP_RIGHT = 270
KEYCODE_DPAD_DOWN_RIGHT = 271
KEYCODE_MEDIA_SKIP_FORWARD = 272
KEYCODE_MEDIA_SKIP_BACKWARD = 273
KEYCODE_MEDIA_STEP_FORWARD = 274
KEYCODE_MEDIA_STEP_BACKWARD = 275
KEYCODE_SOFT_SLEEP = 276
KEYCODE_CUT = 277
KEYCODE_COPY = 278
KEYCODE_PASTE = 279
KEYCODE_SYSTEM_NAVIGATION_UP = 280
KEYCODE_SYSTEM_NAVIGATION_DOWN = 281
KEYCODE_SYSTEM_NAVIGATION_LEFT = 282
KEYCODE_SYSTEM_NAVIGATION_RIGHT = 283
KEYCODE_KEYCODE_ALL_APPS = 284
KEYCODE_KEYCODE_REFRESH = 285
KEYCODE_KEYCODE_THUMBS_UP = 286
KEYCODE_KEYCODE_THUMBS_DOWN = 287
# Event
EVENT_INIT = "init"
EVENT_FRAME = "frame"
# Type # Type
TYPE_INJECT_KEYCODE = 0 TYPE_INJECT_KEYCODE = 0
TYPE_INJECT_TEXT = 1
TYPE_INJECT_TOUCH_EVENT = 2 TYPE_INJECT_TOUCH_EVENT = 2
TYPE_INJECT_SCROLL_EVENT = 3 TYPE_START_APP = 16
TYPE_BACK_OR_SCREEN_ON = 4
TYPE_EXPAND_NOTIFICATION_PANEL = 5
TYPE_EXPAND_SETTINGS_PANEL = 6
TYPE_COLLAPSE_PANELS = 7
TYPE_GET_CLIPBOARD = 8
TYPE_SET_CLIPBOARD = 9
TYPE_SET_SCREEN_POWER_MODE = 10
TYPE_ROTATE_DEVICE = 11
COPY_KEY_NONE = 0
COPY_KEY_COPY = 1
COPY_KEY_CUT = 2
# Lock screen orientation
LOCK_SCREEN_ORIENTATION_UNLOCKED = -1
LOCK_SCREEN_ORIENTATION_INITIAL = -2
LOCK_SCREEN_ORIENTATION_0 = 0
LOCK_SCREEN_ORIENTATION_1 = 1
LOCK_SCREEN_ORIENTATION_2 = 2
LOCK_SCREEN_ORIENTATION_3 = 3
# Screen power mode
POWER_MODE_OFF = 0
POWER_MODE_NORMAL = 2

View file

@ -3,6 +3,8 @@ import struct
from time import sleep from time import sleep
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from mower.utils import config
from . import const from . import const
if TYPE_CHECKING: if TYPE_CHECKING:
@ -83,6 +85,12 @@ class ControlSender:
buttons, buttons,
) )
@inject(const.TYPE_START_APP)
def start_app(self):
app_name = config.conf.APPNAME.encode("utf-8")
length = len(app_name)
return struct.pack(f"!B{length}s", length, app_name)
def tap(self, x, y, hold_time: float = 0.07) -> None: def tap(self, x, y, hold_time: float = 0.07) -> None:
""" """
Tap on screen Tap on screen

View file

@ -1,9 +1,8 @@
from __future__ import annotations
import socket import socket
import struct import struct
import threading import threading
import time import time
from datetime import datetime
from functools import cached_property, wraps from functools import cached_property, wraps
from queue import Queue from queue import Queue
from typing import Any, Callable, Optional from typing import Any, Callable, Optional
@ -13,7 +12,8 @@ from adbutils import AdbConnection, Network
from mower.utils import config from mower.utils import config
from mower.utils import typealias as tp from mower.utils import typealias as tp
from mower.utils.csleep import MowerExit from mower.utils.csleep import MowerExit, csleep
from mower.utils.device import swipe_update
from mower.utils.device.method.adb import ADB from mower.utils.device.method.adb import ADB
from mower.utils.device.method.adb.const import KeyCode from mower.utils.device.method.adb.const import KeyCode
from mower.utils.log import logger from mower.utils.log import logger
@ -27,16 +27,6 @@ SCR_PATH = "/data/local/tmp/scrcpy-server.jar"
SCR_VER = "3.0.2" SCR_VER = "3.0.2"
swipe_update_result = None
def recog_start(func: Callable[[tp.Image], Any] = lambda _: None):
time.sleep(0.1)
config.recog.update()
global swipe_update_result
swipe_update_result = func(config.recog.img)
def retry_scrcpy(func): def retry_scrcpy(func):
@wraps(func) @wraps(func)
def retry_wrapper(self, *args, **kwargs): def retry_wrapper(self, *args, **kwargs):
@ -55,15 +45,12 @@ def retry_scrcpy(func):
class Client: class Client:
def __init__(self, displayid: Optional[int] = None): def __init__(self):
# User accessible # User accessible
self.last_frame: Optional[np.ndarray] = None self.last_frame: Optional[np.ndarray] = None
self.resolution = (1920, 1080) self.resolution = (1920, 1080)
self.control = ControlSender(self) self.control = ControlSender(self)
# Params
self.displayid = displayid
# Need to destroy # Need to destroy
self.__server_stream: Optional[AdbConnection] = None self.__server_stream: Optional[AdbConnection] = None
self.control_socket: Optional[socket.socket] = None self.control_socket: Optional[socket.socket] = None
@ -114,13 +101,13 @@ class Client:
cmdline = f"CLASSPATH={SCR_PATH} app_process /" cmdline = f"CLASSPATH={SCR_PATH} app_process /"
cmdline += f" com.genymobile.scrcpy.Server {SCR_VER} audio=false" cmdline += f" com.genymobile.scrcpy.Server {SCR_VER} audio=false"
cmdline += " control=true tunnel_forward=true send_device_meta=false" cmdline += " control=true tunnel_forward=true send_device_meta=false"
if config.conf.screencap_strategy != "scrcpy": if config.conf.screencap_strategy == "scrcpy":
cmdline += " video=false"
else:
cmdline += f" send_codec_meta=false max_fps={1000 / config.conf.screenshot_interval}" cmdline += f" send_codec_meta=false max_fps={1000 / config.conf.screenshot_interval}"
cmdline += " video_bit_rate=128000000 video_codec=h264" cmdline += " video_bit_rate=128000000 video_codec=h264"
if self.displayid: if config.conf.app_control_strategy == "scrcpy":
cmdline += f" display_id={self.displayid}" cmdline += " new_display=1920x1080/280 vd_system_decorations=false"
else:
cmdline += " video=false"
self.__server_stream: AdbConnection = self.adb.adb_shell(cmdline, True) self.__server_stream: AdbConnection = self.adb.adb_shell(cmdline, True)
# Wait for server to start # Wait for server to start
self.__server_stream.conn.settimeout(3) self.__server_stream.conn.settimeout(3)
@ -164,6 +151,9 @@ class Client:
else: else:
self.control_socket = first_socket self.control_socket = first_socket
if config.conf.app_control_strategy == "scrcpy":
self.launch()
except socket.timeout: except socket.timeout:
raise ConnectionError("Failed to connect scrcpy-server") raise ConnectionError("Failed to connect scrcpy-server")
@ -238,7 +228,7 @@ class Client:
fall and self.control.touch(x0, y0, const.ACTION_DOWN) fall and self.control.touch(x0, y0, const.ACTION_DOWN)
if update and config.recog: if update and config.recog:
thread = threading.Thread(target=recog_start, args=(func,)) thread = threading.Thread(target=swipe_update.start, args=(func,))
thread.start() thread.start()
if (down_time := time.perf_counter()) < start_time + frame_time: if (down_time := time.perf_counter()) < start_time + frame_time:
@ -260,7 +250,7 @@ class Client:
thread.join() thread.join()
if (stop_time := time.perf_counter()) < start_time + interval: if (stop_time := time.perf_counter()) < start_time + interval:
time.sleep(start_time + interval - stop_time) time.sleep(start_time + interval - stop_time)
return swipe_update_result return swipe_update.result
if interval > 0: if interval > 0:
time.sleep(interval) time.sleep(interval)
@ -297,3 +287,49 @@ class Client:
"""send a key event""" """send a key event"""
logger.debug(keycode) logger.debug(keycode)
self.control.send_keyevent(keycode) self.control.send_keyevent(keycode)
@retry_scrcpy
def launch(self):
self.control.start_app()
@retry_scrcpy
def exit(self):
self.adb.exit()
@retry_scrcpy
def home(self):
self.adb.exit()
@retry_scrcpy
def check_device_screen(self):
return True
@retry_scrcpy
def check_current_focus(self) -> bool:
"""check if the application is in the foreground"""
update = False
start_time = datetime.now()
while True:
try:
focus = self.adb.adb_shell("dumpsys window | grep Window")
if (
f"{config.conf.APPNAME}/{config.APP_ACTIVITY_NAME}" not in focus
and "com.hypergryph.arknights.bilibili/com.gsc.welcome.WelcomeActivity"
not in focus
):
if (datetime.now() - start_time).total_seconds() > 40:
self.exit() # 应用卡死
start_time = datetime.now()
self.launch()
update = True
csleep(1)
continue
return update
except MowerExit:
raise
except Exception as e:
logger.exception(e)
update = True
def kill_server(self):
self.adb.kill_server()

View file

@ -0,0 +1,17 @@
import time
from typing import Any, Callable
from mower.utils import config
from mower.utils import typealias as tp
result = None
def start(func: Callable[[tp.Image], Any] = lambda _: None):
if config.conf.screencap_strategy == "scrcpy":
time.sleep(config.conf.screenshot_interval / 500)
else:
time.sleep(0.1)
config.recog.update()
global result
result = func(config.recog.img)

View file

@ -24,15 +24,25 @@ def enter_sss(solver: BaseSolver):
@edge(Scene.SSS_DEPLOY, Scene.SSS_MAIN) @edge(Scene.SSS_DEPLOY, Scene.SSS_MAIN)
@edge(Scene.SSS_REDEPLOY, Scene.SSS_MAIN) @edge(Scene.SSS_REDEPLOY, Scene.SSS_MAIN)
@edge(Scene.SSS_CHOOSE_EC, Scene.SSS_MAIN) @edge(Scene.SSS_CHOOSE_EC, Scene.SSS_MAIN)
@edge(Scene.SSS_ELIMI_AGENCY, Scene.SSS_MAIN)
@edge(Scene.SSS_EC, Scene.SSS_EXIT_CONFIRM) @edge(Scene.SSS_EC, Scene.SSS_EXIT_CONFIRM)
@edge(Scene.SSS_DEVICE, Scene.SSS_EXIT_CONFIRM) @edge(Scene.SSS_DEVICE, Scene.SSS_EXIT_CONFIRM)
@edge(Scene.SSS_OPERATION_COMPLETE, Scene.SSS_DEPLOY) @edge(Scene.SSS_OPERATION_COMPLETE, Scene.SSS_DEPLOY)
@edge(Scene.SSS_SQUAD, Scene.SSS_EXIT_CONFIRM) @edge(Scene.SSS_SQUAD, Scene.SSS_EXIT_CONFIRM)
@edge(Scene.SSS_TERMINATED, Scene.SSS_START)
def sss_back(solver: BaseSolver): def sss_back(solver: BaseSolver):
solver.back() solver.back()
@edge(Scene.SSS_TERMINATED, Scene.SSS_START)
def sss_terminated(solver: BaseSolver):
solver.tap((960, 540))
@edge(Scene.SSS_ELIMI_AGENCY, Scene.SSS_START)
def sss_elimi_agency(solver: BaseSolver):
solver.tap((1500, 1000))
@edge(Scene.SSS_ABANDON_DROP_IN_FIGHT, Scene.OPERATOR_FIGHT) @edge(Scene.SSS_ABANDON_DROP_IN_FIGHT, Scene.OPERATOR_FIGHT)
@edge(Scene.SSS_EXIT_CONFIRM, Scene.SSS_TERMINATED) @edge(Scene.SSS_EXIT_CONFIRM, Scene.SSS_TERMINATED)
def sss_exit(solver: BaseSolver): def sss_exit(solver: BaseSolver):

View file

@ -136,4 +136,6 @@ Thread(target=screenshot_worker, daemon=True).start()
def save_screenshot(img: tp.Image) -> None: def save_screenshot(img: tp.Image) -> None:
filename = f"{time.time_ns()}.jpg" filename = f"{time.time_ns()}.jpg"
logger.debug(filename) logger.debug(filename)
screenshot_queue.put((img, filename)) if config.conf.screenshot > 0:
screenshot_queue.put((img, filename))
config.sc_queue.put(img)

View file

@ -63,13 +63,13 @@ class NumberRecognizer:
digit = cv2.copyMakeBorder( digit = cv2.copyMakeBorder(
digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,) digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,)
) )
score = [] score = {}
for i in target_range: for i in target_range:
im = templates[i] im = templates[i]
result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED) result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
score.append(min_val) score[min_val] = i
value += str(score.index(min(score))) value += str(score[(min(score))])
return value return value

View file

@ -8,9 +8,12 @@ engine = RapidOCR(text_score=0.3)
logger.info("OCR加载完成") logger.info("OCR加载完成")
replacement = {"酪酊之旅": "酩酊之旅"}
def ocr_rec(img: tp.Image | tp.GrayImage) -> str | None: def ocr_rec(img: tp.Image | tp.GrayImage) -> str | None:
result, elapse = engine(img, use_det=False, use_cls=False, use_rec=True) result, elapse = engine(img, use_det=False, use_cls=False, use_rec=True)
elapse = round(elapse[0] * 1000) elapse = round(elapse[0] * 1000)
text = result[0][0].strip() text = result[0][0].strip()
logger.debug(f"{elapse}ms {text}") logger.debug(f"{elapse}ms {text}")
return text return text if text not in replacement else replacement[text]

View file

@ -311,6 +311,8 @@ class Recognizer:
self.scene = Scene.SSS_ACTION self.scene = Scene.SSS_ACTION
elif self.find("sss/accomplished"): elif self.find("sss/accomplished"):
self.scene = Scene.SSS_ACCOMPLISHED self.scene = Scene.SSS_ACCOMPLISHED
elif self.find("sss/ope/use"):
self.scene = Scene.SSS_ELIMI_AGENCY
elif self.find("login_captcha"): elif self.find("login_captcha"):
self.scene = Scene.LOGIN_CAPTCHA self.scene = Scene.LOGIN_CAPTCHA
elif self.find("sign_in/banner"): elif self.find("sign_in/banner"):

View file

@ -150,6 +150,9 @@ color = {
"sss/loading_ex": (1647, 524), "sss/loading_ex": (1647, 524),
"sss/main": (1569, 256), "sss/main": (1569, 256),
"sss/no_drop_check": (1669, 865), "sss/no_drop_check": (1669, 865),
"sss/ope/elimi_agency_on": (1653, 857),
"sss/ope/prts": (1369, 857),
"sss/ope/use": (1627, 965),
"sss/redeploy": (1644, 970), "sss/redeploy": (1644, 970),
"sss/redeploy_ex": (1642, 968), "sss/redeploy_ex": (1642, 968),
"sss/settlement_commission": (1593, 31), "sss/settlement_commission": (1593, 31),

View file

@ -307,6 +307,8 @@ class Scene:
"应急模式额外元件" "应急模式额外元件"
SSS_CHOOSE_EC = 1018 SSS_CHOOSE_EC = 1018
"选择定向元件" "选择定向元件"
SSS_ELIMI_AGENCY = 1019
"保全扫荡确认"
SF_ENTRANCE = 1101 SF_ENTRANCE = 1101
"隐秘战线入口" "隐秘战线入口"
SF_EXIT = 1102 SF_EXIT = 1102
@ -520,6 +522,7 @@ SceneComment = {
1016: "保全作战完成或终止", 1016: "保全作战完成或终止",
1017: "应急模式额外元件", 1017: "应急模式额外元件",
1018: "选择定向元件", 1018: "选择定向元件",
1019: "保全扫荡确认",
1101: "隐秘战线入口", 1101: "隐秘战线入口",
1102: "暂离行动", 1102: "暂离行动",
1103: "选择小队", 1103: "选择小队",

View file

@ -1,5 +1,4 @@
import random import random
import time
from abc import abstractmethod from abc import abstractmethod
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Any, Callable, Literal, Optional, Tuple from typing import Any, Callable, Literal, Optional, Tuple
@ -134,6 +133,8 @@ class BaseSolver:
else: else:
# tp.Coordinate # tp.Coordinate
x, y = poly x, y = poly
x = max(0, min(x, 1920))
y = max(0, min(y, 1080))
return (int(x), int(y)) return (int(x), int(y))
def sleep(self, interval: float = 1) -> None: def sleep(self, interval: float = 1) -> None:
@ -141,16 +142,6 @@ class BaseSolver:
csleep(interval) csleep(interval)
config.recog.update() config.recog.update()
def input(self, referent: str, input_area: tp.Scope, text: str = None) -> None:
"""input text"""
logger.debug(f"{referent=} {input_area=}")
config.device.tap(self.get_pos(input_area))
time.sleep(0.5)
if text is None:
text = input(referent).strip()
config.device.send_text(str(text))
config.device.tap((0, 0))
def find( def find(
self, self,
res: tp.Res, res: tp.Res,

View file

@ -34,6 +34,11 @@ direction_translation = {
"": "Left", "": "Left",
"": "Right", "": "Right",
"": "None", "": "None",
"up": "Up",
"down": "Down",
"left": "Left",
"right": "Right",
"none": "None",
} }

View file

@ -496,6 +496,9 @@ Res = Literal[
"sss/loading_ex", "sss/loading_ex",
"sss/main", "sss/main",
"sss/no_drop_check", "sss/no_drop_check",
"sss/ope/elimi_agency_on",
"sss/ope/prts",
"sss/ope/use",
"sss/operation_complete", "sss/operation_complete",
"sss/redeploy", "sss/redeploy",
"sss/redeploy_ex", "sss/redeploy_ex",

View file

@ -63,4 +63,7 @@ cryptography==43.0.1
SQLAlchemy==2.0.35 SQLAlchemy==2.0.35
# ADB # ADB
adbutils==2.8.0 adbutils==2.8.0
# scrcpy截图
av==14.0.1

View file

@ -11,6 +11,8 @@ annotated-types==0.7.0
# via pydantic # via pydantic
apkutils2==1.0.0 apkutils2==1.0.0
# via adbutils # via adbutils
av==14.0.1
# via -r requirements.in
base45==0.4.4 base45==0.4.4
# via -r requirements.in # via -r requirements.in
blinker==1.8.2 blinker==1.8.2

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import base64
import json import json
import mimetypes import mimetypes
import os import os
@ -41,6 +42,8 @@ def read_log():
msg = config.log_queue.get() msg = config.log_queue.get()
log_lines.append(msg) log_lines.append(msg)
log_lines = log_lines[-100:] log_lines = log_lines[-100:]
if not ws_connections:
continue
data = json.dumps({"type": "log", "data": msg}) data = json.dumps({"type": "log", "data": msg})
for ws in ws_connections: for ws in ws_connections:
ws.send(data) ws.send(data)
@ -49,6 +52,8 @@ def read_log():
def push_config(): def push_config():
while True: while True:
config.push_conf.wait() config.push_conf.wait()
if not ws_connections:
continue
data = json.dumps( data = json.dumps(
{ {
"type": "conf", "type": "conf",
@ -61,8 +66,27 @@ def push_config():
config.push_conf.clear() config.push_conf.clear()
def push_sc():
import cv2
from mower.utils.image import img2bytes
while True:
img = config.sc_queue.get()
if not ws_connections:
continue
img = cv2.resize(img, (480, 270))
img = img2bytes(img)
img = base64.b64encode(img).decode("utf-8")
img = f"data:image/jpeg;base64,{img}"
data = json.dumps({"type": "sc", "data": img})
for ws in ws_connections:
ws.send(data)
Thread(target=read_log, daemon=True).start() Thread(target=read_log, daemon=True).start()
Thread(target=push_config, daemon=True).start() Thread(target=push_config, daemon=True).start()
Thread(target=push_sc, daemon=True).start()
@sock.route("/ws") @sock.route("/ws")

View file

@ -1,4 +1,4 @@
import{_ as U,a as X}from"./IosArrowForward.js";import{ar as z,as as v,av as C,au as p,a_ as q,bT as A,ay as S,B as O,ax as G,b0 as J,D as Q,b as W,j as L,aC as Y,H as b,z as Z,c as F,bH as ee,r as k,s as oe,w as re,bu as V,bv as i,bt as _,bw as s,bC as H,bD as M,bo as r,F as T,by as N,bE as I,bx as te,i as le,aX as ne,b3 as se,k as ie}from"./_plugin-vue_export-helper.js";import{ak as ae}from"./main.js";import{S as de,_ as ce}from"./Scrollbar.js";import{_ as ue}from"./Flex.js";import{_ as me}from"./Image.js";import{_ as ve}from"./Slider.js";import"./get-slot.js";import"./utils.js";import"./use-locale.js";import"./download.js";const pe=z([v("list",` import{_ as U,a as X}from"./IosArrowForward.js";import{ar as z,as as v,av as C,au as b,a_ as q,bT as A,ay as S,B as O,ax as G,b0 as J,D as Q,b as W,j as L,aC as Y,H as p,z as Z,c as F,bH as ee,r as k,s as oe,w as re,bu as V,bv as i,bt as _,bw as s,bC as H,bD as M,bo as r,F as T,by as N,bE as I,bx as te,i as le,aX as ne,b3 as se,k as ie}from"./_plugin-vue_export-helper.js";import{ak as ae}from"./main.js";import{S as de,_ as ce,a as ue}from"./Scrollbar.js";import{_ as me}from"./Flex.js";import{_ as ve}from"./Slider.js";import"./utils.js";import"./use-locale.js";import"./download.js";import"./get-slot.js";const be=z([v("list",`
--n-merged-border-color: var(--n-border-color); --n-merged-border-color: var(--n-border-color);
--n-merged-color: var(--n-color); --n-merged-color: var(--n-color);
--n-merged-color-hover: var(--n-color-hover); --n-merged-color-hover: var(--n-color-hover);
@ -12,7 +12,7 @@ import{_ as U,a as X}from"./IosArrowForward.js";import{ar as z,as as v,av as C,a
list-style-type: none; list-style-type: none;
color: var(--n-text-color); color: var(--n-text-color);
background-color: var(--n-merged-color); background-color: var(--n-merged-color);
`,[C("show-divider",[v("list-item",[z("&:not(:last-child)",[p("divider",` `,[C("show-divider",[v("list-item",[z("&:not(:last-child)",[b("divider",`
background-color: var(--n-merged-border-color); background-color: var(--n-merged-border-color);
`)])])]),C("clickable",[v("list-item",` `)])])]),C("clickable",[v("list-item",`
cursor: pointer; cursor: pointer;
@ -23,13 +23,13 @@ import{_ as U,a as X}from"./IosArrowForward.js";import{ar as z,as as v,av as C,a
border-radius: var(--n-border-radius); border-radius: var(--n-border-radius);
`,[z("&:hover",` `,[z("&:hover",`
background-color: var(--n-merged-color-hover); background-color: var(--n-merged-color-hover);
`,[p("divider",` `,[b("divider",`
background-color: transparent; background-color: transparent;
`)])])]),C("bordered, hoverable",[v("list-item",` `)])])]),C("bordered, hoverable",[v("list-item",`
padding: 12px 20px; padding: 12px 20px;
`),p("header, footer",` `),b("header, footer",`
padding: 12px 20px; padding: 12px 20px;
`)]),p("header, footer",` `)]),b("header, footer",`
padding: 12px 0; padding: 12px 0;
box-sizing: border-box; box-sizing: border-box;
transition: border-color .3s var(--n-bezier); transition: border-color .3s var(--n-bezier);
@ -45,15 +45,15 @@ import{_ as U,a as X}from"./IosArrowForward.js";import{ar as z,as as v,av as C,a
transition: transition:
background-color .3s var(--n-bezier), background-color .3s var(--n-bezier),
border-color .3s var(--n-bezier); border-color .3s var(--n-bezier);
`,[p("prefix",` `,[b("prefix",`
margin-right: 20px; margin-right: 20px;
flex: 0; flex: 0;
`),p("suffix",` `),b("suffix",`
margin-left: 20px; margin-left: 20px;
flex: 0; flex: 0;
`),p("main",` `),b("main",`
flex: 1; flex: 1;
`),p("divider",` `),b("divider",`
height: 1px; height: 1px;
position: absolute; position: absolute;
bottom: 0; bottom: 0;
@ -70,4 +70,4 @@ import{_ as U,a as X}from"./IosArrowForward.js";import{ar as z,as as v,av as C,a
--n-merged-color-hover: var(--n-color-hover-popover); --n-merged-color-hover: var(--n-color-hover-popover);
--n-merged-color: var(--n-color-popover); --n-merged-color: var(--n-color-popover);
--n-merged-border-color: var(--n-border-color-popover); --n-merged-border-color: var(--n-border-color-popover);
`))]),be=Object.assign(Object.assign({},S.props),{size:{type:String,default:"medium"},bordered:Boolean,clickable:Boolean,hoverable:Boolean,showDivider:{type:Boolean,default:!0}}),K=Z("n-list"),_e=O({name:"List",props:be,setup(e){const{mergedClsPrefixRef:o,inlineThemeDisabled:t,mergedRtlRef:m}=G(e),c=J("List",m,o),l=S("List","-list",pe,ae,e,o);Q(K,{showDividerRef:W(e,"showDivider"),mergedClsPrefixRef:o});const f=L(()=>{const{common:{cubicBezierEaseInOut:g},self:{fontSize:R,textColor:n,color:d,colorModal:B,colorPopover:D,borderColor:w,borderColorModal:P,borderColorPopover:j,borderRadius:y,colorHover:$,colorHoverModal:E,colorHoverPopover:h}}=l.value;return{"--n-font-size":R,"--n-bezier":g,"--n-text-color":n,"--n-color":d,"--n-border-radius":y,"--n-border-color":w,"--n-border-color-modal":P,"--n-border-color-popover":j,"--n-color-modal":B,"--n-color-popover":D,"--n-color-hover":$,"--n-color-hover-modal":E,"--n-color-hover-popover":h}}),u=t?Y("list",void 0,f,e):void 0;return{mergedClsPrefix:o,rtlEnabled:c,cssVars:t?void 0:f,themeClass:u==null?void 0:u.themeClass,onRender:u==null?void 0:u.onRender}},render(){var e;const{$slots:o,mergedClsPrefix:t,onRender:m}=this;return m==null||m(),b("ul",{class:[`${t}-list`,this.rtlEnabled&&`${t}-list--rtl`,this.bordered&&`${t}-list--bordered`,this.showDivider&&`${t}-list--show-divider`,this.hoverable&&`${t}-list--hoverable`,this.clickable&&`${t}-list--clickable`,this.themeClass],style:this.cssVars},o.header?b("div",{class:`${t}-list__header`},o.header()):null,(e=o.default)===null||e===void 0?void 0:e.call(o),o.footer?b("div",{class:`${t}-list__footer`},o.footer()):null)}}),fe=O({name:"ListItem",setup(){const e=F(K,null);return e||ee("list-item","`n-list-item` must be placed in `n-list`."),{showDivider:e.showDividerRef,mergedClsPrefix:e.mergedClsPrefixRef}},render(){const{$slots:e,mergedClsPrefix:o}=this;return b("li",{class:`${o}-list-item`},e.prefix?b("div",{class:`${o}-list-item__prefix`},e.prefix()):null,e.default?b("div",{class:`${o}-list-item__main`},e):null,e.suffix?b("div",{class:`${o}-list-item__suffix`},e.suffix()):null,this.showDivider&&b("div",{class:`${o}-list-item__divider`}))}}),ge={style:{"text-align":"center",margin:"0"}},Pe={__name:"DebugConsole",setup(e){const o=F("axios"),t=k([]),m=k(""),c=k([]),l=k(0),f=k(null);oe(()=>{o.get("/debug/log").then(({data:n})=>{t.value=n}),u("runtime.log")});function u(n){m.value=n,o.get(`/debug/log/${n}`).then(({data:d})=>{l.value=0,c.value=d,l.value=c.value.length-1})}const g=L(()=>{var n;return(n=c.value[l.value])==null?void 0:n.screenshot}),R=L(()=>`/debug/screenshot/${g.value}`);return re(l,()=>{var n;(n=f.value)==null||n.scrollTo({top:0})}),(n,d)=>{const B=fe,D=_e,w=de,P=me,j=ve,y=ne,$=se,E=ce,h=ue;return _(),V(h,{style:{width:"100%",height:"100%",gap:"0","overflow-y":"hidden"}},{default:i(()=>[s(w,{style:{width:"220px"}},{default:i(()=>[s(D,{hoverable:"",clickable:"",bordered:""},{default:i(()=>[(_(!0),H(T,null,M(r(t),a=>(_(),V(B,{onClick:x=>u(a)},{default:i(()=>[ie(I(a),1)]),_:2},1032,["onClick"]))),256))]),_:1})]),_:1}),s(h,{vertical:"",style:{flex:"1",height:"100%",overflow:"hidden"}},{default:i(()=>[N("h2",ge,I(r(m)),1),r(g)?(_(),V(P,{key:0,src:r(R),alt:r(g),width:"100%",style:{"max-height":"50%"},"object-fit":"scale-down"},null,8,["src","alt"])):te("",!0),s(w,{ref_key:"log_scroll",ref:f,style:{width:"100%"},"content-style":"font-size: 16px; user-select: text; padding: 0 12px"},{default:i(()=>{var a;return[(_(!0),H(T,null,M((a=r(c)[r(l)])==null?void 0:a.log,x=>(_(),H("div",null,[N("code",null,I(x),1)]))),256))]}),_:1},512),s(h,{align:"center",style:{padding:"0 12px 6px"}},{default:i(()=>[s(j,{style:{flex:"1"},"show-tooltip":"",value:r(l),"onUpdate:value":d[0]||(d[0]=a=>le(l)?l.value=a:null),min:0,max:r(c).length-1,"format-tooltip":a=>{var x;return(x=r(c)[a])==null?void 0:x.time}},null,8,["value","max","format-tooltip"]),s(E,null,{default:i(()=>[s($,{disabled:r(l)==0,onClick:d[1]||(d[1]=a=>l.value--)},{icon:i(()=>[s(y,null,{default:i(()=>[s(r(U))]),_:1})]),_:1},8,["disabled"]),s($,{disabled:r(l)==r(c).length-1,onClick:d[2]||(d[2]=a=>l.value++)},{icon:i(()=>[s(y,null,{default:i(()=>[s(r(X))]),_:1})]),_:1},8,["disabled"])]),_:1})]),_:1})]),_:1})]),_:1})}}};export{Pe as default}; `))]),pe=Object.assign(Object.assign({},S.props),{size:{type:String,default:"medium"},bordered:Boolean,clickable:Boolean,hoverable:Boolean,showDivider:{type:Boolean,default:!0}}),K=Z("n-list"),_e=O({name:"List",props:pe,setup(e){const{mergedClsPrefixRef:o,inlineThemeDisabled:t,mergedRtlRef:m}=G(e),c=J("List",m,o),l=S("List","-list",be,ae,e,o);Q(K,{showDividerRef:W(e,"showDivider"),mergedClsPrefixRef:o});const f=L(()=>{const{common:{cubicBezierEaseInOut:g},self:{fontSize:R,textColor:n,color:d,colorModal:B,colorPopover:D,borderColor:w,borderColorModal:P,borderColorPopover:j,borderRadius:y,colorHover:$,colorHoverModal:E,colorHoverPopover:h}}=l.value;return{"--n-font-size":R,"--n-bezier":g,"--n-text-color":n,"--n-color":d,"--n-border-radius":y,"--n-border-color":w,"--n-border-color-modal":P,"--n-border-color-popover":j,"--n-color-modal":B,"--n-color-popover":D,"--n-color-hover":$,"--n-color-hover-modal":E,"--n-color-hover-popover":h}}),u=t?Y("list",void 0,f,e):void 0;return{mergedClsPrefix:o,rtlEnabled:c,cssVars:t?void 0:f,themeClass:u==null?void 0:u.themeClass,onRender:u==null?void 0:u.onRender}},render(){var e;const{$slots:o,mergedClsPrefix:t,onRender:m}=this;return m==null||m(),p("ul",{class:[`${t}-list`,this.rtlEnabled&&`${t}-list--rtl`,this.bordered&&`${t}-list--bordered`,this.showDivider&&`${t}-list--show-divider`,this.hoverable&&`${t}-list--hoverable`,this.clickable&&`${t}-list--clickable`,this.themeClass],style:this.cssVars},o.header?p("div",{class:`${t}-list__header`},o.header()):null,(e=o.default)===null||e===void 0?void 0:e.call(o),o.footer?p("div",{class:`${t}-list__footer`},o.footer()):null)}}),fe=O({name:"ListItem",setup(){const e=F(K,null);return e||ee("list-item","`n-list-item` must be placed in `n-list`."),{showDivider:e.showDividerRef,mergedClsPrefix:e.mergedClsPrefixRef}},render(){const{$slots:e,mergedClsPrefix:o}=this;return p("li",{class:`${o}-list-item`},e.prefix?p("div",{class:`${o}-list-item__prefix`},e.prefix()):null,e.default?p("div",{class:`${o}-list-item__main`},e):null,e.suffix?p("div",{class:`${o}-list-item__suffix`},e.suffix()):null,this.showDivider&&p("div",{class:`${o}-list-item__divider`}))}}),ge={style:{"text-align":"center",margin:"0"}},De={__name:"DebugConsole",setup(e){const o=F("axios"),t=k([]),m=k(""),c=k([]),l=k(0),f=k(null);oe(()=>{o.get("/debug/log").then(({data:n})=>{t.value=n}),u("runtime.log")});function u(n){m.value=n,o.get(`/debug/log/${n}`).then(({data:d})=>{l.value=0,c.value=d,l.value=c.value.length-1})}const g=L(()=>{var n;return(n=c.value[l.value])==null?void 0:n.screenshot}),R=L(()=>`/debug/screenshot/${g.value}`);return re(l,()=>{var n;(n=f.value)==null||n.scrollTo({top:0})}),(n,d)=>{const B=fe,D=_e,w=de,P=ce,j=ve,y=ne,$=se,E=ue,h=me;return _(),V(h,{style:{width:"100%",height:"100%",gap:"0","overflow-y":"hidden"}},{default:i(()=>[s(w,{style:{width:"220px"}},{default:i(()=>[s(D,{hoverable:"",clickable:"",bordered:""},{default:i(()=>[(_(!0),H(T,null,M(r(t),a=>(_(),V(B,{onClick:x=>u(a)},{default:i(()=>[ie(I(a),1)]),_:2},1032,["onClick"]))),256))]),_:1})]),_:1}),s(h,{vertical:"",style:{flex:"1",height:"100%",overflow:"hidden"}},{default:i(()=>[N("h2",ge,I(r(m)),1),r(g)?(_(),V(P,{key:0,src:r(R),alt:r(g),width:"100%",style:{"max-height":"50%"},"object-fit":"scale-down"},null,8,["src","alt"])):te("",!0),s(w,{ref_key:"log_scroll",ref:f,style:{width:"100%"},"content-style":"font-size: 16px; user-select: text; padding: 0 12px"},{default:i(()=>{var a;return[(_(!0),H(T,null,M((a=r(c)[r(l)])==null?void 0:a.log,x=>(_(),H("div",null,[N("code",null,I(x),1)]))),256))]}),_:1},512),s(h,{align:"center",style:{padding:"0 12px 6px"}},{default:i(()=>[s(j,{style:{flex:"1"},"show-tooltip":"",value:r(l),"onUpdate:value":d[0]||(d[0]=a=>le(l)?l.value=a:null),min:0,max:r(c).length-1,"format-tooltip":a=>{var x;return(x=r(c)[a])==null?void 0:x.time}},null,8,["value","max","format-tooltip"]),s(E,null,{default:i(()=>[s($,{disabled:r(l)==0,onClick:d[1]||(d[1]=a=>l.value--)},{icon:i(()=>[s(y,null,{default:i(()=>[s(r(U))]),_:1})]),_:1},8,["disabled"]),s($,{disabled:r(l)==r(c).length-1,onClick:d[2]||(d[2]=a=>l.value++)},{icon:i(()=>[s(y,null,{default:i(()=>[s(r(X))]),_:1})]),_:1},8,["disabled"])]),_:1})]),_:1})]),_:1})]),_:1})}}};export{De as default};

View file

@ -1,4 +1,4 @@
import{_ as fn}from"./HelpText.js";import{m as mn,n as pn,o as gn,B as At,V as Vt,h as Mt,i as jt,f as yn,b as it,p as bn,q as _t,r as Cn,A as _n,j as kn,s as kt,u as wn,k as Dn,v as Sn,_ as Rn,w as xn}from"./main.js";import{c as zt,g as wt,d as Dt,e as St,f as ne,h as ot,m as st,y as dt,q as ut,i as $n,j as Fe,k as qe,l as D,n as me,o as oe,t as ie,u as Ee,v as za,w as Rt,x as xt,z as be,A as Bt,B as Qe,C as On,D as ct,E as Et,F as It,G as Ut,H as Yt,I as ht,J as ra,K as Tn,a as Pn,p as $t,r as rt,L as Fn,b as An}from"./op_select.js";import{c as ea,j as y,aR as Vn,ai as Nt,H as t,an as Lt,ar as P,as as K,av as H,au as fe,B as Ie,ax as mt,r as R,s as pt,w as Ae,b as Ce,ay as va,aC as Ea,z as Mn,n as qt,bL as Ge,bM as _e,b3 as pe,b8 as oa,aD as Ht,E as Kt,M as Wt,b4 as W,K as Qt,at as Ra,bF as Jt,aI as vt,az as jn,l as zn,D as Bn,aY as Ot,J as En,b2 as Ba,aL as Pe,ap as In,aO as Un,aV as Yn,br as Gt,bt as xe,bu as Je,bv as re,bo as Y,bC as xa,bw as te,i as ia,bx as Xe,by as ae,k as Te,F as Tt,bE as Pt,b9 as Nn,bm as Zt,bG as Ln,aX as qn}from"./_plugin-vue_export-helper.js";import{F as fa,_ as Hn,a as Kn}from"./Select.js";import{u as Ia}from"./use-locale.js";import{V as ft}from"./VirtualList.js";import{F as sa,B as da,a as ua,b as ca,s as Wn}from"./Forward.js";import{_ as aa}from"./Input.js";import{t as Qn,c as Jn,_ as Gn}from"./Tag.js";import{S as Zn,_ as Xn}from"./Scrollbar.js";function el(e,l){const u=ea(Vn,null);return y(()=>e.hljs||(u==null?void 0:u.mergedHljsRef.value))}const Ft=Nt("date",t("svg",{width:"28px",height:"28px",viewBox:"0 0 28 28",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},t("g",{stroke:"none","stroke-width":"1","fill-rule":"evenodd"},t("g",{"fill-rule":"nonzero"},t("path",{d:"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z"}))))),al=Nt("to",t("svg",{viewBox:"0 0 20 20",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},t("g",{stroke:"none","stroke-width":"1",fill:"none","fill-rule":"evenodd"},t("g",{fill:"currentColor","fill-rule":"nonzero"},t("path",{d:"M11.2654,3.20511 C10.9644,2.92049 10.4897,2.93371 10.2051,3.23464 C9.92049,3.53558 9.93371,4.01027 10.2346,4.29489 L15.4737,9.25 L2.75,9.25 C2.33579,9.25 2,9.58579 2,10.0000012 C2,10.4142 2.33579,10.75 2.75,10.75 L15.476,10.75 L10.2346,15.7073 C9.93371,15.9919 9.92049,16.4666 10.2051,16.7675 C10.4897,17.0684 10.9644,17.0817 11.2654,16.797 L17.6826,10.7276 C17.8489,10.5703 17.9489,10.3702 17.9826,10.1614 C17.994,10.1094 18,10.0554 18,10.0000012 C18,9.94241 17.9935,9.88633 17.9812,9.83246 C17.9462,9.62667 17.8467,9.42976 17.6826,9.27455 L11.2654,3.20511 Z"})))));function tl(e,l){const u=mn(e),a=Math.trunc(u.getMonth()/3)+1,i=l-a;return zt(u,u.getMonth()+i*3)}function nl(e){const{textColor2:l,fontSize:u,fontWeightStrong:a,textColor3:i}=e;return{textColor:l,fontSize:u,fontWeightStrong:a,"mono-3":"#a0a1a7","hue-1":"#0184bb","hue-2":"#4078f2","hue-3":"#a626a4","hue-4":"#50a14f","hue-5":"#e45649","hue-5-2":"#c91243","hue-6":"#986801","hue-6-2":"#c18401",lineNumberTextColor:i}}const ll={name:"Code",common:Lt,self:nl},rl=P([K("code",` import{_ as fn}from"./HelpText.js";import{m as mn,n as pn,o as gn,B as At,V as Vt,h as Mt,i as jt,f as yn,b as it,p as bn,q as _t,r as Cn,A as _n,j as kn,s as kt,u as wn,k as Dn,v as Sn,_ as Rn,w as xn}from"./main.js";import{c as zt,g as wt,d as Dt,e as St,f as ne,h as ot,m as st,y as dt,q as ut,i as $n,j as Fe,k as qe,l as D,n as me,o as oe,t as ie,u as Ee,v as za,w as Rt,x as xt,z as be,A as Bt,B as Qe,C as On,D as ct,E as Et,F as It,G as Ut,H as Yt,I as ht,J as ra,K as Tn,a as Pn,p as $t,r as rt,L as Fn,b as An}from"./op_select.js";import{c as ea,j as y,aR as Vn,ai as Nt,H as t,an as Lt,ar as P,as as K,av as H,au as fe,B as Ie,ax as mt,r as R,s as pt,w as Ae,b as Ce,ay as va,aC as Ea,z as Mn,n as qt,bL as Ge,bM as _e,b3 as pe,b8 as oa,aD as Ht,E as Kt,M as Wt,b4 as W,K as Qt,at as Ra,bF as Jt,aI as vt,az as jn,l as zn,D as Bn,aY as Ot,J as En,b2 as Ba,aL as Pe,ap as In,aO as Un,aV as Yn,br as Gt,bt as xe,bu as Je,bv as re,bo as Y,bC as xa,bw as te,i as ia,bx as Xe,by as ae,k as Te,F as Tt,bE as Pt,b9 as Nn,bm as Zt,bG as Ln,aX as qn}from"./_plugin-vue_export-helper.js";import{F as fa,_ as Hn,a as Kn}from"./Select.js";import{u as Ia}from"./use-locale.js";import{V as ft}from"./VirtualList.js";import{F as sa,B as da,a as ua,b as ca,s as Wn}from"./Forward.js";import{_ as aa}from"./Input.js";import{t as Qn,c as Jn,_ as Gn}from"./Tag.js";import{S as Zn,a as Xn}from"./Scrollbar.js";function el(e,l){const u=ea(Vn,null);return y(()=>e.hljs||(u==null?void 0:u.mergedHljsRef.value))}const Ft=Nt("date",t("svg",{width:"28px",height:"28px",viewBox:"0 0 28 28",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},t("g",{stroke:"none","stroke-width":"1","fill-rule":"evenodd"},t("g",{"fill-rule":"nonzero"},t("path",{d:"M21.75,3 C23.5449254,3 25,4.45507456 25,6.25 L25,21.75 C25,23.5449254 23.5449254,25 21.75,25 L6.25,25 C4.45507456,25 3,23.5449254 3,21.75 L3,6.25 C3,4.45507456 4.45507456,3 6.25,3 L21.75,3 Z M23.5,9.503 L4.5,9.503 L4.5,21.75 C4.5,22.7164983 5.28350169,23.5 6.25,23.5 L21.75,23.5 C22.7164983,23.5 23.5,22.7164983 23.5,21.75 L23.5,9.503 Z M21.75,4.5 L6.25,4.5 C5.28350169,4.5 4.5,5.28350169 4.5,6.25 L4.5,8.003 L23.5,8.003 L23.5,6.25 C23.5,5.28350169 22.7164983,4.5 21.75,4.5 Z"}))))),al=Nt("to",t("svg",{viewBox:"0 0 20 20",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},t("g",{stroke:"none","stroke-width":"1",fill:"none","fill-rule":"evenodd"},t("g",{fill:"currentColor","fill-rule":"nonzero"},t("path",{d:"M11.2654,3.20511 C10.9644,2.92049 10.4897,2.93371 10.2051,3.23464 C9.92049,3.53558 9.93371,4.01027 10.2346,4.29489 L15.4737,9.25 L2.75,9.25 C2.33579,9.25 2,9.58579 2,10.0000012 C2,10.4142 2.33579,10.75 2.75,10.75 L15.476,10.75 L10.2346,15.7073 C9.93371,15.9919 9.92049,16.4666 10.2051,16.7675 C10.4897,17.0684 10.9644,17.0817 11.2654,16.797 L17.6826,10.7276 C17.8489,10.5703 17.9489,10.3702 17.9826,10.1614 C17.994,10.1094 18,10.0554 18,10.0000012 C18,9.94241 17.9935,9.88633 17.9812,9.83246 C17.9462,9.62667 17.8467,9.42976 17.6826,9.27455 L11.2654,3.20511 Z"})))));function tl(e,l){const u=mn(e),a=Math.trunc(u.getMonth()/3)+1,i=l-a;return zt(u,u.getMonth()+i*3)}function nl(e){const{textColor2:l,fontSize:u,fontWeightStrong:a,textColor3:i}=e;return{textColor:l,fontSize:u,fontWeightStrong:a,"mono-3":"#a0a1a7","hue-1":"#0184bb","hue-2":"#4078f2","hue-3":"#a626a4","hue-4":"#50a14f","hue-5":"#e45649","hue-5-2":"#c91243","hue-6":"#986801","hue-6-2":"#c18401",lineNumberTextColor:i}}const ll={name:"Code",common:Lt,self:nl},rl=P([K("code",`
font-size: var(--n-font-size); font-size: var(--n-font-size);
font-family: var(--n-font-family); font-family: var(--n-font-family);
`,[H("show-line-numbers",` `,[H("show-line-numbers",`

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
.log[data-v-b6949d6f]{overflow:hidden;flex:1}.task-table[data-v-b6949d6f]{max-width:600px}.task-table th[data-v-b6949d6f]{padding:2px 16px}.task-table td[data-v-b6949d6f]{height:24px;padding:2px 8px}.task-table td[data-v-b6949d6f]:last-child{width:100%}.action-container[data-v-b6949d6f]{display:flex;align-items:center;gap:12px}.scroll-container[data-v-b6949d6f]{display:flex;align-items:center;gap:4px}.expand[data-v-b6949d6f]{flex-grow:1}.toggle-table-collapse-btn[data-v-b6949d6f]{position:absolute;top:12px;right:12px}.toggle-fullscreen-btn[data-v-b6949d6f]{position:absolute;top:12px;right:50px}.log-bg[data-v-b6949d6f]{content:"";width:100%;height:100%;position:absolute;top:0;left:0;opacity:var(--15833a31);background-image:url(/bg.webp);background-repeat:no-repeat;background-size:cover;background-position:65% 50%;pointer-events:none}.hljs-date{color:#f0a020!important;font-weight:700}.hljs-time{color:#2080f0!important;font-weight:700}.hljs-room{color:#18a058!important;font-weight:700}.hljs-operator{color:#d03050!important}.hljs-info{font-weight:700}.hljs-warning{color:#f0a020!important;font-weight:700}.hljs-error{color:#d03050!important;font-weight:700}.hljs-scene{font-style:italic} .log[data-v-c4feeca6]{overflow:hidden;flex:1}.task-table[data-v-c4feeca6]{position:relative;max-width:600px}.task-table th[data-v-c4feeca6]{padding:2px 16px}.task-table td[data-v-c4feeca6]{height:24px;padding:2px 8px}.task-table td[data-v-c4feeca6]:last-child{width:100%}.action-container[data-v-c4feeca6]{display:flex;align-items:center;gap:12px}.scroll-container[data-v-c4feeca6]{display:flex;align-items:center;gap:4px}.expand[data-v-c4feeca6]{flex-grow:1}.toggle-table-collapse-btn[data-v-c4feeca6]{position:absolute;top:0;right:0}.toggle-fullscreen-btn[data-v-c4feeca6]{position:absolute;top:0;right:38px}.log-bg[data-v-c4feeca6]{content:"";width:100%;height:100%;position:absolute;top:0;left:0;opacity:var(--55f59a8a);background-image:url(/bg.webp);background-repeat:no-repeat;background-size:cover;background-position:65% 50%;pointer-events:none;z-index:14}.sc[data-v-c4feeca6]{max-width:480px;max-height:270px;border-radius:6px;z-index:15}.hljs-date{color:#f0a020!important;font-weight:700}.hljs-time{color:#2080f0!important;font-weight:700}.hljs-room{color:#18a058!important;font-weight:700}.hljs-operator{color:#d03050!important}.hljs-info{font-weight:700}.hljs-warning{color:#f0a020!important;font-weight:700}.hljs-error{color:#d03050!important;font-weight:700}.hljs-scene{font-style:italic}

42
ui/dist/assets/Log.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
.sss-container[data-v-2dffb781]{display:flex;width:100%;gap:8px}.wrapper[data-v-2dffb781]{white-space:pre-wrap;-webkit-user-select:text;user-select:text}.title[data-v-2dffb781]{font-size:18px;font-weight:500;margin-bottom:6px}p[data-v-d479d5bf]{margin:0 0 10px}.misc-container[data-v-d479d5bf]{display:flex;align-items:center;gap:12px}.header[data-v-d479d5bf]{margin:12px 0}.tasktable[data-v-6e42e723]{margin-top:4px;width:100%;overflow:scroll}.tasktable table[data-v-6e42e723]{border-collapse:collapse;width:100%}.btn-clear[data-v-6e42e723]{margin:4px}@media screen and (max-width: 1399px){.tasktable[data-v-6e42e723]{max-height:300px}.tasktable td[data-v-6e42e723]{width:10.2857142857%}.tasktable td[data-v-6e42e723]:first-child{width:10%}.tasktable td[data-v-6e42e723]:nth-child(2){width:18%}.tasktable thead[data-v-6e42e723]{position:sticky;top:0;background-color:#7ea5b4;z-index:1}}@media screen and (min-width: 1400px){.tasktable td[data-v-6e42e723]{width:10.2857142857%}.tasktable td[data-v-6e42e723]:first-child{width:10%}.tasktable td[data-v-6e42e723]:nth-child(2){width:18%}.tasktable thead[data-v-6e42e723]{background-color:#7ea5b4}}.class1[data-v-6e42e723]{background-color:var(--06f96d6a);text-align:center;vertical-align:middle}.class2[data-v-6e42e723]{background-color:var(--292d8683);text-align:center;vertical-align:middle}.custom-tag[data-v-6e42e723]{width:100%;height:100%;justify-content:space-between}.today[data-v-6e42e723]{font-weight:400;font-size:12px}.activity[data-v-6e42e723]{align-items:center;gap:4px!important}.card-title[data-v-6e42e723]{transition:.3s}.disabled[data-v-6e42e723]{color:var(--6d545694)}.form-item[data-v-6e42e723]{margin:0 0 4px}p[data-v-748f667d]{margin:2px 0}h4[data-v-748f667d]{margin:12px 0 8px}table[data-v-748f667d]{width:100%}td[data-v-748f667d]:nth-child(1){width:80px}.ignore-blacklist[data-v-748f667d]{margin-bottom:10px;display:flex;gap:12px}.h4[data-v-748f667d]{font-size:16px;font-weight:500}.maa-shop[data-v-748f667d]{margin:8px 0}.item[data-v-748f667d]{font-weight:500;font-size:16px}p[data-v-707c6f48]{margin:0 0 8px}h4[data-v-707c6f48]{margin:12px 0 10px}.big-table[data-v-707c6f48]{margin-top:10px;max-width:320px}.big-table th[data-v-707c6f48]{text-align:center}.big-table tr[data-v-707c6f48]{width:70px}.big-table td[data-v-707c6f48]{height:24px}.big-table td[data-v-707c6f48]:nth-child(1){width:70px;text-align:center}.big-table td[data-v-707c6f48]:nth-child(2){width:420px}.final[data-v-707c6f48]{margin:16px 0 0}.item[data-v-e95953da]{font-weight:500;font-size:16px}.n-divider[data-v-e95953da]:not(.n-divider--vertical){margin:6px 0}.subtitle[data-v-31c5d919]{margin:12px 0 6px}.misc-container{margin-top:12px;display:flex;align-items:center;gap:12px}.email-title[data-v-7cbc22ce]{width:100%}.expand[data-v-7cbc22ce]{flex-grow:1}.email-table[data-v-7cbc22ce]{width:100%;margin-bottom:12px}.email-test[data-v-7cbc22ce]{display:flex;align-items:center;gap:16px}.email-mode[data-v-7cbc22ce]{margin-left:20px}.email-label[data-v-7cbc22ce]{width:68px}p[data-v-7cbc22ce]{margin:0 0 10px}.mt-16[data-v-7cbc22ce]{margin-top:16px}.threshold[data-v-7e026566]{display:flex;align-items:center;gap:14px;width:100%}.mower-basic[data-v-7e026566]{width:100%}.mower-basic td[data-v-7e026566]:nth-child(1){width:120px}.mower-basic td[data-v-7e026566]:nth-child(3){padding-left:6px;width:40px}.riic-conf[data-v-7e026566]{width:100%}.riic-conf td[data-v-7e026566]:nth-child(1){width:130px}.riic-conf td[data-v-7e026566]:nth-child(3){padding-left:12px;width:120px}.coord td[data-v-7e026566]{width:120px}.coord td[data-v-7e026566]:nth-child(1),.coord td[data-v-7e026566]:nth-child(3){width:30px}.coord td[data-v-7e026566]:nth-child(2){padding-right:30px}.coord-label[data-v-7e026566]{width:40px;padding-left:8px}p[data-v-7e026566]{margin:0 0 8px}h4[data-v-7e026566]{margin:12px 0 10px}.time-table[data-v-7e026566]{width:100%;margin-bottom:12px}.time-table td[data-v-7e026566]:nth-child(1){width:40px}.scale[data-v-7e026566]{width:60px;text-align:right}.scale-apply[data-v-7e026566]{margin-left:24px}.waiting-table th[data-v-7e026566],.waiting-table td[data-v-7e026566]{padding:4px;min-width:70px;width:100px}.waiting-table th[data-v-7e026566]:first-child,.waiting-table td[data-v-7e026566]:first-child{width:auto;padding:4px 8px}@media (max-width: 1399px){.grid-two{margin:0 0 -10px;width:100%;max-width:600px}.grid-left{display:grid;row-gap:10px;grid-template-columns:100%}.grid-right{display:grid;row-gap:10px;grid-template-columns:100%;margin-top:10px}}@media (min-width: 1400px){.grid-two{display:grid;grid-template-columns:minmax(0px,1fr) minmax(0px,1fr);align-items:flex-start;gap:5px}.grid-left,.grid-right{display:grid;gap:5px;grid-template-columns:100%;max-width:600px}}.n-divider:not(.n-divider--vertical){margin:14px 0 8px} .sss-container[data-v-2dffb781]{display:flex;width:100%;gap:8px}.wrapper[data-v-2dffb781]{white-space:pre-wrap;-webkit-user-select:text;user-select:text}.title[data-v-2dffb781]{font-size:18px;font-weight:500;margin-bottom:6px}p[data-v-d479d5bf]{margin:0 0 10px}.misc-container[data-v-d479d5bf]{display:flex;align-items:center;gap:12px}.header[data-v-d479d5bf]{margin:12px 0}.tasktable[data-v-6e42e723]{margin-top:4px;width:100%;overflow:scroll}.tasktable table[data-v-6e42e723]{border-collapse:collapse;width:100%}.btn-clear[data-v-6e42e723]{margin:4px}@media screen and (max-width: 1399px){.tasktable[data-v-6e42e723]{max-height:300px}.tasktable td[data-v-6e42e723]{width:10.2857142857%}.tasktable td[data-v-6e42e723]:first-child{width:10%}.tasktable td[data-v-6e42e723]:nth-child(2){width:18%}.tasktable thead[data-v-6e42e723]{position:sticky;top:0;background-color:#7ea5b4;z-index:1}}@media screen and (min-width: 1400px){.tasktable td[data-v-6e42e723]{width:10.2857142857%}.tasktable td[data-v-6e42e723]:first-child{width:10%}.tasktable td[data-v-6e42e723]:nth-child(2){width:18%}.tasktable thead[data-v-6e42e723]{background-color:#7ea5b4}}.class1[data-v-6e42e723]{background-color:var(--06f96d6a);text-align:center;vertical-align:middle}.class2[data-v-6e42e723]{background-color:var(--292d8683);text-align:center;vertical-align:middle}.custom-tag[data-v-6e42e723]{width:100%;height:100%;justify-content:space-between}.today[data-v-6e42e723]{font-weight:400;font-size:12px}.activity[data-v-6e42e723]{align-items:center;gap:4px!important}.card-title[data-v-6e42e723]{transition:.3s}.disabled[data-v-6e42e723]{color:var(--6d545694)}.form-item[data-v-6e42e723]{margin:0 0 4px}p[data-v-748f667d]{margin:2px 0}h4[data-v-748f667d]{margin:12px 0 8px}table[data-v-748f667d]{width:100%}td[data-v-748f667d]:nth-child(1){width:80px}.ignore-blacklist[data-v-748f667d]{margin-bottom:10px;display:flex;gap:12px}.h4[data-v-748f667d]{font-size:16px;font-weight:500}.maa-shop[data-v-748f667d]{margin:8px 0}.item[data-v-748f667d]{font-weight:500;font-size:16px}p[data-v-707c6f48]{margin:0 0 8px}h4[data-v-707c6f48]{margin:12px 0 10px}.big-table[data-v-707c6f48]{margin-top:10px;max-width:320px}.big-table th[data-v-707c6f48]{text-align:center}.big-table tr[data-v-707c6f48]{width:70px}.big-table td[data-v-707c6f48]{height:24px}.big-table td[data-v-707c6f48]:nth-child(1){width:70px;text-align:center}.big-table td[data-v-707c6f48]:nth-child(2){width:420px}.final[data-v-707c6f48]{margin:16px 0 0}.item[data-v-e95953da]{font-weight:500;font-size:16px}.n-divider[data-v-e95953da]:not(.n-divider--vertical){margin:6px 0}.subtitle[data-v-31c5d919]{margin:12px 0 6px}.misc-container{margin-top:12px;display:flex;align-items:center;gap:12px}.email-title[data-v-7cbc22ce]{width:100%}.expand[data-v-7cbc22ce]{flex-grow:1}.email-table[data-v-7cbc22ce]{width:100%;margin-bottom:12px}.email-test[data-v-7cbc22ce]{display:flex;align-items:center;gap:16px}.email-mode[data-v-7cbc22ce]{margin-left:20px}.email-label[data-v-7cbc22ce]{width:68px}p[data-v-7cbc22ce]{margin:0 0 10px}.mt-16[data-v-7cbc22ce]{margin-top:16px}.threshold[data-v-32cd0fe1]{display:flex;align-items:center;gap:14px;width:100%}.mower-basic[data-v-32cd0fe1]{width:100%}.mower-basic td[data-v-32cd0fe1]:nth-child(1){width:120px}.mower-basic td[data-v-32cd0fe1]:nth-child(3){padding-left:6px;width:40px}.riic-conf[data-v-32cd0fe1]{width:100%}.riic-conf td[data-v-32cd0fe1]:nth-child(1){width:130px}.riic-conf td[data-v-32cd0fe1]:nth-child(3){padding-left:12px;width:120px}.coord td[data-v-32cd0fe1]{width:120px}.coord td[data-v-32cd0fe1]:nth-child(1),.coord td[data-v-32cd0fe1]:nth-child(3){width:30px}.coord td[data-v-32cd0fe1]:nth-child(2){padding-right:30px}.coord-label[data-v-32cd0fe1]{width:40px;padding-left:8px}p[data-v-32cd0fe1]{margin:0 0 8px}h4[data-v-32cd0fe1]{margin:12px 0 10px}.time-table[data-v-32cd0fe1]{width:100%;margin-bottom:12px}.time-table td[data-v-32cd0fe1]:nth-child(1){width:40px}.scale[data-v-32cd0fe1]{width:60px;text-align:right}.scale-apply[data-v-32cd0fe1]{margin-left:24px}.waiting-table th[data-v-32cd0fe1],.waiting-table td[data-v-32cd0fe1]{padding:4px;min-width:70px;width:100px}.waiting-table th[data-v-32cd0fe1]:first-child,.waiting-table td[data-v-32cd0fe1]:first-child{width:auto;padding:4px 8px}@media (max-width: 1399px){.grid-two{margin:0 0 -10px;width:100%;max-width:600px}.grid-left{display:grid;row-gap:10px;grid-template-columns:100%}.grid-right{display:grid;row-gap:10px;grid-template-columns:100%;margin-top:10px}}@media (min-width: 1400px){.grid-two{display:grid;grid-template-columns:minmax(0px,1fr) minmax(0px,1fr);align-items:flex-start;gap:5px}.grid-left,.grid-right{display:grid;gap:5px;grid-template-columns:100%;max-width:600px}}.n-divider:not(.n-divider--vertical){margin:14px 0 8px}

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
import{c as Q,q as kt,w as lt,u as Ct,ai as qe,H as c,as as b,av as O,ar as E,z as Ue,ay as le,B as Z,ax as Te,r as K,D as Oe,aZ as Ie,j as _,aB as ne,ak as St,au as G,b as D,L as Be,bN as Pt,s as $t,aY as re,aC as Ve,aD as _t,aG as Ft,l as Le,bH as be,b2 as J,N as Ot,bO as We,b4 as Bt,be as st,A as qt,az as Tt,b3 as Se,bh as zt,bg as It,bF as Lt,aI as jt,T as At,F as Dt,aL as He,n as Et,br as Mt,bP as Nt,bQ as Ut,bt as Vt,bu as Wt,bv as Ht,bw as Gt,bo as Pe}from"./_plugin-vue_export-helper.js";import{F as dt,G as ut,H as Xt,S as ct,I as ft,W as gt,J as ht,K as Yt,A as Kt,L as Ge,M as Zt,s as Jt,j as Qt,N as er,O as tr}from"./main.js";import{_ as rr,D as nr,N as ir}from"./Image.js";import{E as ar}from"./Input.js";import{d as or}from"./download.js";import{m as lr}from"./index.js";import{r as sr,M as dr}from"./op_select.js";import{_ as ur}from"./Select.js";function cr(t,e,r){var n;const i=Q(t,null);if(i===null)return;const a=(n=kt())===null||n===void 0?void 0:n.proxy;lt(r,o),o(r.value),Ct(()=>{o(void 0,r.value)});function o(u,s){if(!i)return;const f=i[e];s!==void 0&&l(f,s),u!==void 0&&d(f,u)}function l(u,s){u[s]||(u[s]=[]),u[s].splice(u[s].findIndex(f=>f===a),1)}function d(u,s){u[s]||(u[s]=[]),~u[s].findIndex(f=>f===a)||u[s].push(a)}}const fr=qe("attach",c("svg",{viewBox:"0 0 16 16",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},c("g",{stroke:"none","stroke-width":"1",fill:"none","fill-rule":"evenodd"},c("g",{fill:"currentColor","fill-rule":"nonzero"},c("path",{d:"M3.25735931,8.70710678 L7.85355339,4.1109127 C8.82986412,3.13460197 10.4127766,3.13460197 11.3890873,4.1109127 C12.365398,5.08722343 12.365398,6.67013588 11.3890873,7.64644661 L6.08578644,12.9497475 C5.69526215,13.3402718 5.06209717,13.3402718 4.67157288,12.9497475 C4.28104858,12.5592232 4.28104858,11.9260582 4.67157288,11.5355339 L9.97487373,6.23223305 C10.1701359,6.0369709 10.1701359,5.72038841 9.97487373,5.52512627 C9.77961159,5.32986412 9.4630291,5.32986412 9.26776695,5.52512627 L3.96446609,10.8284271 C3.18341751,11.6094757 3.18341751,12.8758057 3.96446609,13.6568542 C4.74551468,14.4379028 6.01184464,14.4379028 6.79289322,13.6568542 L12.0961941,8.35355339 C13.4630291,6.98671837 13.4630291,4.77064094 12.0961941,3.40380592 C10.7293591,2.0369709 8.51328163,2.0369709 7.14644661,3.40380592 L2.55025253,8 C2.35499039,8.19526215 2.35499039,8.51184464 2.55025253,8.70710678 C2.74551468,8.90236893 3.06209717,8.90236893 3.25735931,8.70710678 Z"}))))),gr=qe("trash",c("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512"},c("path",{d:"M432,144,403.33,419.74A32,32,0,0,1,371.55,448H140.46a32,32,0,0,1-31.78-28.26L80,144",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;"}),c("rect",{x:"32",y:"64",width:"448",height:"80",rx:"16",ry:"16",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;"}),c("line",{x1:"312",y1:"240",x2:"200",y2:"352",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;"}),c("line",{x1:"312",y1:"352",x2:"200",y2:"240",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;"}))),hr=qe("cancel",c("svg",{viewBox:"0 0 16 16",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},c("g",{stroke:"none","stroke-width":"1",fill:"none","fill-rule":"evenodd"},c("g",{fill:"currentColor","fill-rule":"nonzero"},c("path",{d:"M2.58859116,2.7156945 L2.64644661,2.64644661 C2.82001296,2.47288026 3.08943736,2.45359511 3.2843055,2.58859116 L3.35355339,2.64644661 L8,7.293 L12.6464466,2.64644661 C12.8417088,2.45118446 13.1582912,2.45118446 13.3535534,2.64644661 C13.5488155,2.84170876 13.5488155,3.15829124 13.3535534,3.35355339 L8.707,8 L13.3535534,12.6464466 C13.5271197,12.820013 13.5464049,13.0894374 13.4114088,13.2843055 L13.3535534,13.3535534 C13.179987,13.5271197 12.9105626,13.5464049 12.7156945,13.4114088 L12.6464466,13.3535534 L8,8.707 L3.35355339,13.3535534 C3.15829124,13.5488155 2.84170876,13.5488155 2.64644661,13.3535534 C2.45118446,13.1582912 2.45118446,12.8417088 2.64644661,12.6464466 L7.293,8 L2.64644661,3.35355339 C2.47288026,3.17998704 2.45359511,2.91056264 2.58859116,2.7156945 L2.64644661,2.64644661 L2.58859116,2.7156945 Z"}))))),pr=qe("retry",c("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512"},c("path",{d:"M320,146s24.36-12-64-12A160,160,0,1,0,416,294",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-miterlimit: 10; stroke-width: 32px;"}),c("polyline",{points:"256 58 336 138 256 218",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;"}))),mr=b("form",[O("inline",` import{c as Q,q as kt,w as lt,u as Ct,ai as qe,H as c,as as b,av as O,ar as E,z as Ue,ay as le,B as Z,ax as Te,r as K,D as Oe,aZ as Ie,j as _,aB as ne,ak as St,au as G,b as D,L as Be,bN as Pt,s as $t,aY as re,aC as Ve,aD as _t,aG as Ft,l as Le,bH as be,b2 as J,N as Ot,bO as We,b4 as Bt,be as st,A as qt,az as Tt,b3 as Se,bh as zt,bg as It,bF as Lt,aI as jt,T as At,F as Dt,aL as He,n as Et,br as Mt,bP as Nt,bQ as Ut,bt as Vt,bu as Wt,bv as Ht,bw as Gt,bo as Pe}from"./_plugin-vue_export-helper.js";import{F as dt,G as ut,H as Xt,S as ct,I as ft,W as gt,J as ht,K as Yt,A as Kt,L as Ge,M as Zt,s as Jt,j as Qt,N as er,O as tr}from"./main.js";import{_ as rr,D as nr,N as ir}from"./Scrollbar.js";import{E as ar}from"./Input.js";import{d as or}from"./download.js";import{m as lr}from"./index.js";import{r as sr,M as dr}from"./op_select.js";import{_ as ur}from"./Select.js";function cr(t,e,r){var n;const i=Q(t,null);if(i===null)return;const a=(n=kt())===null||n===void 0?void 0:n.proxy;lt(r,o),o(r.value),Ct(()=>{o(void 0,r.value)});function o(u,s){if(!i)return;const f=i[e];s!==void 0&&l(f,s),u!==void 0&&d(f,u)}function l(u,s){u[s]||(u[s]=[]),u[s].splice(u[s].findIndex(f=>f===a),1)}function d(u,s){u[s]||(u[s]=[]),~u[s].findIndex(f=>f===a)||u[s].push(a)}}const fr=qe("attach",c("svg",{viewBox:"0 0 16 16",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},c("g",{stroke:"none","stroke-width":"1",fill:"none","fill-rule":"evenodd"},c("g",{fill:"currentColor","fill-rule":"nonzero"},c("path",{d:"M3.25735931,8.70710678 L7.85355339,4.1109127 C8.82986412,3.13460197 10.4127766,3.13460197 11.3890873,4.1109127 C12.365398,5.08722343 12.365398,6.67013588 11.3890873,7.64644661 L6.08578644,12.9497475 C5.69526215,13.3402718 5.06209717,13.3402718 4.67157288,12.9497475 C4.28104858,12.5592232 4.28104858,11.9260582 4.67157288,11.5355339 L9.97487373,6.23223305 C10.1701359,6.0369709 10.1701359,5.72038841 9.97487373,5.52512627 C9.77961159,5.32986412 9.4630291,5.32986412 9.26776695,5.52512627 L3.96446609,10.8284271 C3.18341751,11.6094757 3.18341751,12.8758057 3.96446609,13.6568542 C4.74551468,14.4379028 6.01184464,14.4379028 6.79289322,13.6568542 L12.0961941,8.35355339 C13.4630291,6.98671837 13.4630291,4.77064094 12.0961941,3.40380592 C10.7293591,2.0369709 8.51328163,2.0369709 7.14644661,3.40380592 L2.55025253,8 C2.35499039,8.19526215 2.35499039,8.51184464 2.55025253,8.70710678 C2.74551468,8.90236893 3.06209717,8.90236893 3.25735931,8.70710678 Z"}))))),gr=qe("trash",c("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512"},c("path",{d:"M432,144,403.33,419.74A32,32,0,0,1,371.55,448H140.46a32,32,0,0,1-31.78-28.26L80,144",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;"}),c("rect",{x:"32",y:"64",width:"448",height:"80",rx:"16",ry:"16",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;"}),c("line",{x1:"312",y1:"240",x2:"200",y2:"352",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;"}),c("line",{x1:"312",y1:"352",x2:"200",y2:"240",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;"}))),hr=qe("cancel",c("svg",{viewBox:"0 0 16 16",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},c("g",{stroke:"none","stroke-width":"1",fill:"none","fill-rule":"evenodd"},c("g",{fill:"currentColor","fill-rule":"nonzero"},c("path",{d:"M2.58859116,2.7156945 L2.64644661,2.64644661 C2.82001296,2.47288026 3.08943736,2.45359511 3.2843055,2.58859116 L3.35355339,2.64644661 L8,7.293 L12.6464466,2.64644661 C12.8417088,2.45118446 13.1582912,2.45118446 13.3535534,2.64644661 C13.5488155,2.84170876 13.5488155,3.15829124 13.3535534,3.35355339 L8.707,8 L13.3535534,12.6464466 C13.5271197,12.820013 13.5464049,13.0894374 13.4114088,13.2843055 L13.3535534,13.3535534 C13.179987,13.5271197 12.9105626,13.5464049 12.7156945,13.4114088 L12.6464466,13.3535534 L8,8.707 L3.35355339,13.3535534 C3.15829124,13.5488155 2.84170876,13.5488155 2.64644661,13.3535534 C2.45118446,13.1582912 2.45118446,12.8417088 2.64644661,12.6464466 L7.293,8 L2.64644661,3.35355339 C2.47288026,3.17998704 2.45359511,2.91056264 2.58859116,2.7156945 L2.64644661,2.64644661 L2.58859116,2.7156945 Z"}))))),pr=qe("retry",c("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512"},c("path",{d:"M320,146s24.36-12-64-12A160,160,0,1,0,416,294",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-miterlimit: 10; stroke-width: 32px;"}),c("polyline",{points:"256 58 336 138 256 218",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;"}))),mr=b("form",[O("inline",`
width: 100%; width: 100%;
display: inline-flex; display: inline-flex;
align-items: flex-start; align-items: flex-start;

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
var _r=Object.defineProperty;var Fr=(t,n,e)=>n in t?_r(t,n,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[n]=e;var h=(t,n,e)=>Fr(t,typeof n!="symbol"?n+"":n,e);import{B as le,H as u,ai as Rr,bH as Vr,z as En,c as bt,j as F,r as te,b3 as De,b8 as at,ar as V,as as K,av as se,au as Ye,at as An,ay as fe,ax as Je,bF as $n,w as lt,b as Be,aI as Xt,n as ut,D as zn,aC as dt,J as Yr,b2 as ke,aD as Hr,E as Sr,aL as Z,M as Br,ap as Un,an as Ln,aO as qn,aV as Wn,bN as Er,b0 as vt,b4 as ft,bM as dn,bR as Nt,t as _t,L as Ar,N as $r,aY as ct,bS as zr,bj as fn,C as Ur,A as Pe,aj as Lr,aG as mn,v as hn,bL as gn,a_ as qr,bT as Wr}from"./_plugin-vue_export-helper.js";import{m as k,o as Te,P as et,Q as jr,f as Qr,b as qt,R as Gr,n as Xr,B as Zr,V as Kr,h as Jr,i as ea,q as pn,r as ta,T as na,A as Wt,U as ra,X as aa,Y as oa}from"./main.js";import{e as jn,u as Zt}from"./use-locale.js";import{F as ia,A as sa}from"./Select.js";import{_ as Ze}from"./Input.js";import{_ as la}from"./Scrollbar.js";import{g as ua}from"./get-slot.js";import{m as ca}from"./index.js";import{_ as Qn}from"./Avatar.js";import{_ as da}from"./Tag.js";const fa=le({name:"ArrowUp",render(){return u("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20"},u("g",{fill:"none"},u("path",{d:"M3.13 9.163a.5.5 0 1 0 .74.674L9.5 3.67V17.5a.5.5 0 0 0 1 0V3.672l5.63 6.165a.5.5 0 0 0 .738-.674l-6.315-6.916a.746.746 0 0 0-.632-.24a.746.746 0 0 0-.476.24L3.131 9.163z",fill:"currentColor"})))}}),Gn=le({name:"Remove",render(){return u("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512"},u("line",{x1:"400",y1:"256",x2:"112",y2:"256",style:` var _r=Object.defineProperty;var Fr=(t,n,e)=>n in t?_r(t,n,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[n]=e;var h=(t,n,e)=>Fr(t,typeof n!="symbol"?n+"":n,e);import{B as le,H as u,ai as Rr,bH as Vr,z as En,c as bt,j as F,r as te,b3 as De,b8 as at,ar as V,as as K,av as se,au as Ye,at as An,ay as fe,ax as Je,bF as $n,w as lt,b as Be,aI as Xt,n as ut,D as zn,aC as dt,J as Yr,b2 as ke,aD as Hr,E as Sr,aL as Z,M as Br,ap as Un,an as Ln,aO as qn,aV as Wn,bN as Er,b0 as vt,b4 as ft,bM as dn,bR as Nt,t as _t,L as Ar,N as $r,aY as ct,bS as zr,bj as fn,C as Ur,A as Pe,aj as Lr,aG as mn,v as hn,bL as gn,a_ as qr,bT as Wr}from"./_plugin-vue_export-helper.js";import{m as k,o as Te,P as et,Q as jr,f as Qr,b as qt,R as Gr,n as Xr,B as Zr,V as Kr,h as Jr,i as ea,q as pn,r as ta,T as na,A as Wt,U as ra,X as aa,Y as oa}from"./main.js";import{e as jn,u as Zt}from"./use-locale.js";import{F as ia,A as sa}from"./Select.js";import{_ as Ze}from"./Input.js";import{a as la}from"./Scrollbar.js";import{g as ua}from"./get-slot.js";import{m as ca}from"./index.js";import{_ as Qn}from"./Avatar.js";import{_ as da}from"./Tag.js";const fa=le({name:"ArrowUp",render(){return u("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20"},u("g",{fill:"none"},u("path",{d:"M3.13 9.163a.5.5 0 1 0 .74.674L9.5 3.67V17.5a.5.5 0 0 0 1 0V3.672l5.63 6.165a.5.5 0 0 0 .738-.674l-6.315-6.916a.746.746 0 0 0-.632-.24a.746.746 0 0 0-.476.24L3.131 9.163z",fill:"currentColor"})))}}),Gn=le({name:"Remove",render(){return u("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512"},u("line",{x1:"400",y1:"256",x2:"112",y2:"256",style:`
fill: none; fill: none;
stroke: currentColor; stroke: currentColor;
stroke-linecap: round; stroke-linecap: round;

BIN
ui/public/black.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -3,7 +3,7 @@ import { storeToRefs } from 'pinia'
import { useMowerStore } from '@/stores/mower' import { useMowerStore } from '@/stores/mower'
const mower_store = useMowerStore() const mower_store = useMowerStore()
const { log, log_mobile, running, log_lines, task_list, waiting, get_task_id } = const { log, log_mobile, running, log_lines, task_list, waiting, get_task_id, sc_uri } =
storeToRefs(mower_store) storeToRefs(mower_store)
const { get_tasks } = mower_store const { get_tasks } = mower_store
const axios = inject('axios') const axios = inject('axios')
@ -54,19 +54,19 @@ function stop() {
}) })
} }
import PlayIcon from '@vicons/ionicons5/Play' import { useConfigStore } from '@/stores/config'
import StopIcon from '@vicons/ionicons5/Stop' import FullscreenIcon from '@vicons/fluent/ArrowMaximize20Regular'
import AddIcon from '@vicons/ionicons5/Add'
import CollapseIcon from '@vicons/fluent/PanelTopContract20Regular' import CollapseIcon from '@vicons/fluent/PanelTopContract20Regular'
import ExpandIcon from '@vicons/fluent/PanelTopExpand20Regular' import ExpandIcon from '@vicons/fluent/PanelTopExpand20Regular'
import FullscreenIcon from '@vicons/fluent/ArrowMaximize20Regular' import AddIcon from '@vicons/ionicons5/Add'
import PlayIcon from '@vicons/ionicons5/Play'
import StopIcon from '@vicons/ionicons5/Stop'
const show_task_table = ref(true) const show_task_table = ref(true)
const show_task = ref(false) const show_task = ref(false)
const add_task = ref(true) const add_task = ref(true)
provide('show_task', show_task) provide('show_task', show_task)
provide('add_task', add_task) provide('add_task', add_task)
import { useConfigStore } from '@/stores/config'
const config_store = useConfigStore() const config_store = useConfigStore()
const { conf } = storeToRefs(config_store) const { conf } = storeToRefs(config_store)
@ -88,13 +88,23 @@ const stop_options = [
function fullscreen() { function fullscreen() {
document.documentElement.requestFullscreen() document.documentElement.requestFullscreen()
} }
const sc_preview = ref(true)
</script> </script>
<template> <template>
<div class="home-container"> <div class="home-container">
<div class="log-bg"></div> <div class="log-bg"></div>
<n-image
v-if="sc_preview"
preview-disabled
width="100%"
class="sc"
:src="sc_uri == '' ? '/black.jpg' : sc_uri"
object-fit="scale-down"
/>
<n-table class="task-table" size="small" :single-line="false"> <n-table class="task-table" size="small" :single-line="false">
<thead> <thead @click="sc_preview = !sc_preview">
<tr> <tr>
<th>时间</th> <th>时间</th>
<th :colspan="2">任务</th> <th :colspan="2">任务</th>
@ -121,6 +131,33 @@ function fullscreen() {
</tr> </tr>
</template> </template>
</tbody> </tbody>
<n-button
class="toggle-table-collapse-btn"
size="small"
@click="show_task_table = !show_task_table"
:focusable="false"
v-if="mobile"
>
<template #icon>
<n-icon>
<collapse-icon v-if="show_task_table" />
<expand-icon v-else />
</n-icon>
</template>
</n-button>
<n-button
class="toggle-fullscreen-btn"
size="small"
@click="fullscreen"
:focusable="false"
v-if="mobile"
>
<template #icon>
<n-icon>
<fullscreen-icon />
</n-icon>
</template>
</n-button>
</n-table> </n-table>
<n-log <n-log
class="log" class="log"
@ -172,33 +209,6 @@ function fullscreen() {
<span class="scroll-label" v-if="!mobile">自动滚动</span> <span class="scroll-label" v-if="!mobile">自动滚动</span>
</div> </div>
</div> </div>
<n-button
class="toggle-table-collapse-btn"
size="small"
@click="show_task_table = !show_task_table"
:focusable="false"
v-if="mobile"
>
<template #icon>
<n-icon>
<collapse-icon v-if="show_task_table" />
<expand-icon v-else />
</n-icon>
</template>
</n-button>
<n-button
class="toggle-fullscreen-btn"
size="small"
@click="fullscreen"
:focusable="false"
v-if="mobile"
>
<template #icon>
<n-icon>
<fullscreen-icon />
</n-icon>
</template>
</n-button>
</div> </div>
</template> </template>
@ -209,6 +219,7 @@ function fullscreen() {
} }
.task-table { .task-table {
position: relative;
max-width: 600px; max-width: 600px;
th { th {
@ -243,14 +254,14 @@ function fullscreen() {
.toggle-table-collapse-btn { .toggle-table-collapse-btn {
position: absolute; position: absolute;
top: 12px; top: 0;
right: 12px; right: 0;
} }
.toggle-fullscreen-btn { .toggle-fullscreen-btn {
position: absolute; position: absolute;
top: 12px; top: 0;
right: 50px; right: 38px;
} }
.log-bg { .log-bg {
@ -266,6 +277,14 @@ function fullscreen() {
background-size: cover; background-size: cover;
background-position: 65% 50%; background-position: 65% 50%;
pointer-events: none; pointer-events: none;
z-index: 14;
}
.sc {
max-width: 480px;
max-height: 270px;
border-radius: 6px;
z-index: 15;
} }
</style> </style>

View file

@ -95,6 +95,9 @@ const app_control_options = computed(() => {
if (conf.value.emulator.name == 'MuMu12') { if (conf.value.emulator.name == 'MuMu12') {
result.push({ label: 'MuMu模拟器12应用管理器', value: 'mumumanager' }) result.push({ label: 'MuMu模拟器12应用管理器', value: 'mumumanager' })
} }
if (conf.value.screencap_strategy == 'scrcpy' && conf.value.control_strategy == 'scrcpy') {
result.push({ label: 'scrcpy virtual display', value: 'scrcpy' })
}
return result return result
}) })

View file

@ -36,6 +36,8 @@ export const useMowerStore = defineStore('mower', () => {
const { conf, timestamp, post_conf } = storeToRefs(config_store) const { conf, timestamp, post_conf } = storeToRefs(config_store)
const { parse_config } = config_store const { parse_config } = config_store
const sc_uri = ref('')
function listen_ws() { function listen_ws() {
let backend_url let backend_url
if (import.meta.env.DEV) { if (import.meta.env.DEV) {
@ -55,6 +57,8 @@ export const useMowerStore = defineStore('mower', () => {
timestamp.value = data.time timestamp.value = data.time
conf.value = parse_config(data.data) conf.value = parse_config(data.data)
} }
} else if (data.type == 'sc') {
sc_uri.value = data.data
} }
} }
} }
@ -79,6 +83,7 @@ export const useMowerStore = defineStore('mower', () => {
log_mobile, log_mobile,
log_lines, log_lines,
ws, ws,
sc_uri,
running, running,
waiting, waiting,
listen_ws, listen_ws,