feat: 增強自动战斗文件选择功能,支持多级路径和相对目录 (#15174)

* chore: 先依照保全派駐週期粗略分類

* chore: 換個位置

* chore: 換成用地圖名稱分類

* chore: 再改 再改

* chore: 別空白了 伺服器會被殺死的

* chore: 補上下拉選單顯示的 json 檔案名稱,避免解析錯誤

* chore: 幫展開後的下拉選單加上寬度限制

* Revert "chore: 幫展開後的下拉選單加上寬度限制"

This reverts commit d5f80c9d6e.

* feat: 新增文件树视图项样式

* perf: 优化自动战斗下拉列表

* feat: 统一样式

* chore: 删除多余调用

---------

Co-authored-by: uye <99072975+ABA2396@users.noreply.github.com>
This commit is contained in:
HY
2026-01-05 20:29:13 +08:00
committed by GitHub
parent 718cf790da
commit 2af35681eb
73 changed files with 5419 additions and 26 deletions

View File

@@ -0,0 +1,815 @@
{
"minimum_required": "v5.15.0",
"stage_name": "尚蜀夜市",
"actions": [],
"doc": {
"title": "任务专用*-保全派驻-尚蜀夜市-阿斯卡纶-伊桑-自适应补给元件",
"title_color": "dark",
"details": "做任务用,别在应急难度开始\n本作业可完成自适应补给元件的两个任务+招募8次术师任务+招募8次特种任务\n如果后面两个任务完成慢就把这个作业的blacklist里面的干员删掉就算后面他打不过也能完成任务\n一命通关视频已上传求三连\n═══════════════════════════════════\n作业代码maa://50505\n目前只能手动编队所有工具人请尽量选择费用低的干员练度最好精二最低精一满级\n所有工具人技能不要选只能开一次的技能类似山2技能那种和接敌才能放的技能类似锏3技能那种否则MAA会一直放技能也不要选攻击范围太奇怪的类似黑3技能那种\n请在确认导能原件选择【自适应补给元件】、战术装备特种B其余全选A、手动编队并阵容确认后再点击开始\n作业作者萨拉托加\n作业视频【MAA保全派驻 自适应补给元件任务+招募8次术师特种任务】 https://www.bilibili.com/video/BV1nJ5kz6E31/?share_source=copy_web&vd_source=3fd5040fe25f6a00e19e6072bcccfa4e\nJSON作者萨拉托加\n═══════════════════════════════════\n不包括核心选择的额外干员\n重装6可选塞雷娅余或其他能打的盾\n医疗2强度高的奶可选奶羊M3闪灵等\n辅助3可选令浊蒂魔王塑心或者其他低费辅助\n特种7优先选地刺千万别选行商陷阱师炼金师怪杰分支的干员\n═══════════════════════════════════\n有问题反馈进群545928846评论区反馈不一定能及时回复\n部分核心可根据自己需求修改作业文件替换但不可发上作业站用此作业默认同意",
"details_color": "dark"
},
"groups": [],
"opers": [
{
"name": "阿斯卡纶",
"skill": 1,
"skill_usage": 0
},
{
"name": "伊桑",
"skill": 1,
"skill_usage": 0
}
],
"type": "SSS",
"buff": "自适应补给元件",
"equipment": ["A", "A", "A", "A", "A", "A", "A", "B"],
"strategy": "优选策略",
"tool_men": {
"vanguard": 0,
"guard": 0,
"defender": 6,
"sniper": 0,
"caster": 0,
"medic": 2,
"supporter": 3,
"special": 7
},
"drops": ["特种", "术师", "辅助", "无需增调干员", "定向部署支援系统"],
"blacklist": [
"罗比菈塔",
"新约能天使",
"掠风",
"白铁",
"伺夜",
"豆苗",
"夜半",
"缪尔赛思",
"森蚺",
"极光",
"迷迭香",
"早露",
"菲亚梅塔",
"承曦格雷伊",
"莫斯提马",
"死芒",
"凯尔希",
"艾拉",
"多萝西",
"引星棘刺",
"锡人",
"阿",
"钼铅",
"裁度",
"琳琅诗怀雅",
"空构",
"老鲤",
"霜华",
"乌有",
"罗宾",
"孑",
"玛露西尔",
"阿罗玛",
"戴菲恩",
"林",
"和弦",
"卡涅利安",
"深靛",
"夕",
"爱丽丝",
"薄绿",
"蜜蜡",
"阿兰娜",
"凯瑟琳",
"PhonoR-0",
"Friston-3",
"THRM-EX",
"异客",
"伊芙利特",
"寒檀",
"莱恩哈特",
"惊蛰",
"蚀清",
"天火",
"星源",
"炎狱炎熔",
"布丁",
"格雷伊",
"远山",
"炎熔",
"假日威龙陈",
"埃拉托",
"奥斯塔",
"截云",
"熔泉",
"慑砂",
"送葬人",
"陨星",
"白雪",
"铅踝",
"松果",
"泰拉大陆调查团",
"正义骑士号",
"黑",
"洋灰",
"火哨",
"斥罪",
"号角",
"火神",
"灰毫",
"泥岩",
"车尔尼",
"暮落",
"石棉",
"坚雷",
"阿米娅",
"风笛",
"黑键",
"伊内丝",
"晓歌",
"格拉尼",
"苇草",
"野鬃",
"历阵锐枪芬",
"谜图",
"红豆",
"翎羽",
"W",
"U-Official",
"12F",
"Lancet-2"
],
"stages": [
{
"stage_name": "巷道里",
"strategies": [
{
"core": "自适应补给元件",
"tool_men": {},
"location": [3, 2],
"direction": "none"
},
{
"tool_men": {
"defender": 1
},
"location": [5, 2],
"direction": "Left"
},
{
"tool_men": {
"special": 1
},
"location": [4, 2],
"direction": "Left"
},
{
"tool_men": {
"supporter": 1
},
"location": [5, 3],
"direction": "Left"
},
{
"tool_men": {
"medic": 1
},
"location": [5, 1],
"direction": "Down"
},
{
"tool_men": {
"defender": 1
},
"location": [5, 2],
"direction": "Left"
},
{
"tool_men": {
"special": 1
},
"location": [4, 2],
"direction": "Left"
},
{
"tool_men": {
"supporter": 1
},
"location": [5, 3],
"direction": "Left"
},
{
"tool_men": {
"medic": 1
},
"location": [5, 1],
"direction": "Down"
},
{
"tool_men": {
"special": 2
},
"location": [4, 2],
"direction": "Left"
},
{
"core": "阿斯卡纶",
"tool_men": {
"special": 1
},
"location": [4, 2],
"direction": "Right"
},
{
"tool_men": {
"supporter": 99
},
"location": [5, 3],
"direction": "Left"
},
{
"tool_men": {
"defender": 99
},
"location": [5, 2],
"direction": "Left"
},
{
"core": "丛林用示踪信标",
"tool_men": {
"medic": 99
},
"location": [5, 1],
"direction": "Down"
}
],
"draw_as_possible": true,
"actions": [
{
"type": "二倍速"
}
],
"retry_times": 99
},
{
"stage_name": "楼台边",
"strategies": [
{
"core": "自适应补给元件",
"tool_men": {},
"location": [5, 3],
"direction": "none"
},
{
"tool_men": {
"defender": 1
},
"location": [2, 3],
"direction": "Right"
},
{
"tool_men": {
"special": 1
},
"location": [3, 3],
"direction": "Left"
},
{
"tool_men": {
"supporter": 1
},
"location": [2, 2],
"direction": "Right"
},
{
"tool_men": {
"medic": 1
},
"location": [1, 2],
"direction": "Right"
},
{
"tool_men": {
"defender": 1
},
"location": [2, 3],
"direction": "Right"
},
{
"tool_men": {
"special": 1
},
"location": [3, 3],
"direction": "Left"
},
{
"tool_men": {
"supporter": 1
},
"location": [2, 2],
"direction": "Right"
},
{
"tool_men": {
"medic": 1
},
"location": [1, 2],
"direction": "Right"
},
{
"core": "阿斯卡纶",
"tool_men": {
"special": 3
},
"location": [3, 3],
"direction": "Left"
},
{
"tool_men": {
"special": 2
},
"location": [1, 3],
"direction": "Right"
},
{
"tool_men": {
"defender": 3
},
"location": [2, 3],
"direction": "Right"
},
{
"core": "伊桑",
"tool_men": {
"special": 3
},
"location": [1, 3],
"direction": "Right"
},
{
"tool_men": {
"supporter": 99
},
"location": [2, 2],
"direction": "Right"
},
{
"tool_men": {
"caster": 99
},
"location": [2, 2],
"direction": "Right"
},
{
"tool_men": {
"defender": 99
},
"location": [2, 3],
"direction": "Right"
},
{
"core": "丛林用示踪信标",
"tool_men": {
"medic": 99
},
"location": [1, 2],
"direction": "Right"
}
],
"draw_as_possible": true,
"actions": [
{
"type": "二倍速"
}
],
"retry_times": 99
},
{
"stage_name": "墓地旁",
"strategies": [
{
"core": "自适应补给元件",
"tool_men": {},
"location": [5, 2],
"direction": "none"
},
{
"tool_men": {
"defender": 1
},
"location": [2, 4],
"direction": "Right"
},
{
"tool_men": {
"special": 1
},
"location": [3, 4],
"direction": "Left"
},
{
"tool_men": {
"supporter": 1
},
"location": [2, 3],
"direction": "Right"
},
{
"tool_men": {
"medic": 1
},
"location": [2, 5],
"direction": "Up"
},
{
"tool_men": {
"defender": 1
},
"location": [1, 4],
"direction": "Right"
},
{
"tool_men": {
"special": 1
},
"location": [3, 4],
"direction": "Left"
},
{
"tool_men": {
"medic": 1
},
"location": [2, 5],
"direction": "Up"
},
{
"tool_men": {
"defender": 1
},
"location": [2, 4],
"direction": "Right"
},
{
"core": "阿斯卡纶",
"tool_men": {
"special": 3
},
"location": [3, 4],
"direction": "Left"
},
{
"tool_men": {
"defender": 2
},
"location": [2, 4],
"direction": "Right"
},
{
"core": "伊桑",
"tool_men": {
"special": 4
},
"location": [1, 4],
"direction": "Right"
},
{
"tool_men": {
"supporter": 2
},
"location": [2, 3],
"direction": "Right"
},
{
"tool_men": {
"defender": 1
},
"location": [2, 4],
"direction": "Right"
},
{
"tool_men": {
"supporter": 99
},
"location": [2, 3],
"direction": "Right"
},
{
"tool_men": {
"caster": 99
},
"location": [2, 3],
"direction": "Right"
},
{
"tool_men": {
"defender": 99
},
"location": [2, 4],
"direction": "Right"
},
{
"core": "丛林用示踪信标",
"tool_men": {
"medic": 99
},
"location": [2, 5],
"direction": "Up"
}
],
"draw_as_possible": true,
"actions": [
{
"type": "二倍速"
}
],
"retry_times": 99
},
{
"stage_name": "舞台上",
"strategies": [
{
"core": "自适应补给元件",
"tool_men": {},
"location": [1, 2],
"direction": "none"
},
{
"tool_men": {
"defender": 6
},
"location": [3, 4],
"direction": "Up"
},
{
"core": "阿斯卡纶",
"tool_men": {
"special": 5
},
"location": [3, 3],
"direction": "Right"
},
{
"core": "伊桑",
"tool_men": {
"special": 5
},
"location": [3, 5],
"direction": "Right"
},
{
"tool_men": {
"medic": 1
},
"location": [4, 4],
"direction": "Left"
},
{
"tool_men": {
"supporter": 99
},
"location": [2, 4],
"direction": "Right"
},
{
"tool_men": {
"medic": 4
},
"location": [4, 4],
"direction": "Left"
},
{
"tool_men": {
"special": 99
},
"location": [3, 6],
"direction": "Up"
},
{
"tool_men": {
"defender": 99
},
"location": [3, 4],
"direction": "Up"
},
{
"tool_men": {
"caster": 99
},
"location": [2, 4],
"direction": "Right"
},
{
"core": "丛林用示踪信标",
"tool_men": {
"medic": 99
},
"location": [4, 4],
"direction": "Left"
}
],
"draw_as_possible": true,
"actions": [
{
"type": "二倍速"
}
],
"retry_times": 99
},
{
"stage_name": "城门下",
"strategies": [
{
"core": "自适应补给元件",
"tool_men": {},
"location": [2, 3],
"direction": "none"
},
{
"tool_men": {
"defender": 6
},
"location": [6, 5],
"direction": "Up"
},
{
"tool_men": {
"special": 4
},
"location": [5, 4],
"direction": "Right"
},
{
"core": "阿斯卡纶",
"tool_men": {
"special": 1
},
"location": [5, 4],
"direction": "Up"
},
{
"core": "伊桑",
"tool_men": {
"special": 5
},
"location": [7, 5],
"direction": "Left"
},
{
"tool_men": {
"medic": 1
},
"location": [6, 6],
"direction": "Up"
},
{
"tool_men": {
"supporter": 99
},
"location": [7, 4],
"direction": "Left"
},
{
"tool_men": {
"medic": 4
},
"location": [6, 6],
"direction": "Up"
},
{
"tool_men": {
"special": 99
},
"location": [6, 4],
"direction": "Down"
},
{
"tool_men": {
"defender": 99
},
"location": [6, 5],
"direction": "Up"
},
{
"tool_men": {
"caster": 99
},
"location": [7, 4],
"direction": "Left"
},
{
"core": "丛林用示踪信标",
"tool_men": {
"medic": 99
},
"location": [6, 6],
"direction": "Up"
}
],
"draw_as_possible": true,
"actions": [
{
"type": "二倍速"
}
],
"retry_times": 99
},
{
"stage_name": "天地间",
"strategies": [
{
"core": "自适应补给元件",
"tool_men": {},
"location": [1, 3],
"direction": "none"
},
{
"tool_men": {
"defender": 6
},
"location": [2, 5],
"direction": "Right"
},
{
"core": "阿斯卡纶",
"tool_men": {
"special": 5
},
"location": [3, 5],
"direction": "Up"
},
{
"core": "伊桑",
"tool_men": {
"special": 5
},
"location": [2, 4],
"direction": "Down"
},
{
"tool_men": {
"medic": 1
},
"location": [2, 6],
"direction": "Up"
},
{
"tool_men": {
"supporter": 99
},
"location": [1, 6],
"direction": "Right"
},
{
"tool_men": {
"medic": 4
},
"location": [2, 6],
"direction": "Up"
},
{
"tool_men": {
"special": 99
},
"location": [3, 4],
"direction": "Down"
},
{
"tool_men": {
"defender": 6
},
"location": [1, 5],
"direction": "Right"
},
{
"tool_men": {
"defender": 99
},
"location": [2, 5],
"direction": "Right"
},
{
"tool_men": {
"caster": 99
},
"location": [1, 6],
"direction": "Right"
},
{
"core": "丛林用示踪信标",
"tool_men": {
"medic": 99
},
"location": [2, 6],
"direction": "Up"
}
],
"draw_as_possible": true,
"actions": [
{
"type": "二倍速"
}
],
"retry_times": 99
}
]
}

View File

@@ -0,0 +1,989 @@
{
"minimum_required": "v5.15.0",
"stage_name": "尚蜀夜市",
"actions": [],
"doc": {
"title": "保全派驻-尚蜀夜市-维什戴尔+阿斯卡纶+Mon3tr-天工夜行套装",
"title_color": "dark",
"details": "应急一命通关视频已上传,求三连\n═══════════════════════════════════\n作业代码maa://50469\n目前只能手动编队所有工具人请尽量选择费用低的干员练度最好精二最低精一满级\n所有工具人技能不要选只能开一次的技能类似山2技能那种和接敌才能放的技能类似锏3技能那种否则MAA会一直放技能也不要选攻击范围太奇怪的类似黑3技能那种\n请在确认导能原件选择【天工夜行套装】、战术装备术士和特种选B其余全选A、手动编队并阵容确认后再点击开始\n作业作者萨拉托加\n作业视频【MAA保全派驻 尚蜀夜市 应急一命通关】 https://www.bilibili.com/video/BV1mG5vzwEsR/?share_source=copy_web&vd_source=3fd5040fe25f6a00e19e6072bcccfa4e\nJSON作者萨拉托加\n═══════════════════════════════════\n不包括核心选择的额外干员工具人\n先锋4选有不需要接敌就能回费的技能的先锋不要选接敌回费的\n术士4尽量选20费左右的术士如果选群法要带减费模组\n重装3优先选自回血的奶盾例如塞雷娅黍临光\n特种6优先选地刺别选行商注意:MAA目前有bug如果你选了陷阱师炼金师怪杰分支的干员会不放人只能选别的分支\n═══════════════════════════════════\n有问题反馈进群545928846评论区反馈不一定能及时回复\n部分核心可根据自己需求修改作业文件替换但不可发上作业站用此作业默认同意",
"details_color": "dark"
},
"groups": [],
"opers": [
{
"name": "Mon3tr",
"skill": 2,
"skill_usage": 1
},
{
"name": "阿斯卡纶",
"skill": 1,
"skill_usage": 0
},
{
"name": "维什戴尔",
"skill": 1,
"skill_usage": 0
}
],
"type": "SSS",
"buff": "天工夜行套装",
"equipment": ["A", "A", "B", "A", "A", "A", "A", "B"],
"strategy": "优选策略",
"tool_men": {
"vanguard": 4,
"guard": 0,
"defender": 3,
"sniper": 0,
"caster": 4,
"medic": 0,
"supporter": 0,
"special": 6
},
"drops": ["辅助", "无需增调干员", "狙击", "术师", "先锋", "重装", "夜行钩爪模块"],
"blacklist": [
"罗比菈塔",
"掠风",
"白铁",
"伺夜",
"豆苗",
"夜半",
"缪尔赛思",
"森蚺",
"极光",
"迷迭香",
"早露",
"菲亚梅塔",
"承曦格雷伊",
"莫斯提马",
"死芒",
"凯尔希",
"异客",
"伊芙利特",
"寒檀",
"莱恩哈特",
"惊蛰",
"蚀清",
"天火",
"星源",
"炎狱炎熔",
"布丁",
"格雷伊",
"远山",
"炎熔",
"假日威龙陈",
"埃拉托",
"奥斯塔",
"截云",
"熔泉",
"慑砂",
"送葬人",
"陨星",
"白雪",
"铅踝",
"松果",
"泰拉大陆调查团",
"正义骑士号",
"黑",
"洋灰",
"火哨",
"斥罪",
"号角",
"火神",
"灰毫",
"泥岩",
"车尔尼",
"暮落",
"石棉",
"坚雷",
"阿米娅",
"风笛",
"黑键",
"伊内丝",
"晓歌",
"格拉尼",
"苇草",
"野鬃",
"历阵锐枪芬",
"谜图",
"红豆",
"翎羽",
"W",
"U-Official",
"12F",
"Lancet-2"
],
"stages": [
{
"stage_name": "巷道里",
"strategies": [
{
"tool_men": {
"vanguard": 1
},
"location": [5, 2],
"direction": "Left"
},
{
"tool_men": {
"vanguard": 1
},
"location": [6, 2],
"direction": "Left"
},
{
"tool_men": {
"caster": 1
},
"location": [5, 1],
"direction": "Down"
},
{
"tool_men": {
"supporter": 1
},
"location": [5, 3],
"direction": "Right"
},
{
"core": "天工夜行套装",
"tool_men": {},
"location": [3, 2],
"direction": "none"
},
{
"core": "阿斯卡纶",
"tool_men": {
"special": 2
},
"location": [5, 2],
"direction": "Left"
},
{
"core": "维什戴尔",
"tool_men": {
"special": 2
},
"location": [5, 1],
"direction": "Down"
},
{
"tool_men": {
"defender": 1
},
"location": [6, 2],
"direction": "Left"
},
{
"tool_men": {
"caster": 1
},
"location": [5, 3],
"direction": "Left"
},
{
"tool_men": {
"special": 99,
"caster": 99
},
"location": [5, 3],
"direction": "Left"
},
{
"core": "丛林用示踪信标",
"tool_men": {
"defender": 99
},
"location": [6, 2],
"direction": "Left"
}
],
"draw_as_possible": true,
"actions": [
{
"type": "二倍速"
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [1, 2],
"direction": "none",
"cost": 48
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [6, 4],
"direction": "none",
"cost": 49
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [5, 4],
"direction": "none",
"cost": 50
}
],
"retry_times": 9
},
{
"stage_name": "楼台边",
"strategies": [
{
"tool_men": {
"vanguard": 1
},
"location": [3, 3],
"direction": "Right"
},
{
"tool_men": {
"vanguard": 1
},
"location": [2, 3],
"direction": "Right"
},
{
"tool_men": {
"caster": 1
},
"location": [2, 2],
"direction": "Right"
},
{
"tool_men": {
"supporter": 1
},
"location": [5, 4],
"direction": "Left"
},
{
"tool_men": {
"caster": 1
},
"location": [2, 4],
"direction": "Right"
},
{
"core": "天工夜行套装",
"tool_men": {},
"location": [1, 4],
"direction": "none"
},
{
"tool_men": {
"supporter": 1
},
"location": [2, 4],
"direction": "Right"
},
{
"core": "阿斯卡纶",
"tool_men": {
"special": 2
},
"location": [3, 3],
"direction": "Up"
},
{
"core": "维什戴尔",
"tool_men": {
"special": 2
},
"location": [2, 2],
"direction": "Right"
},
{
"tool_men": {
"defender": 1
},
"location": [2, 3],
"direction": "Right"
},
{
"core": "Mon3tr",
"tool_men": {
"special": 2
},
"location": [2, 4],
"direction": "Right"
},
{
"core": "重构体",
"tool_men": {},
"location": [1, 5],
"direction": "none"
},
{
"tool_men": {
"supporter": 99
},
"location": [5, 4],
"direction": "Left"
},
{
"tool_men": {
"caster": 99
},
"location": [5, 4],
"direction": "Left"
},
{
"core": "丛林用示踪信标",
"tool_men": {
"defender": 99
},
"location": [2, 3],
"direction": "Right"
}
],
"draw_as_possible": true,
"actions": [
{
"type": "二倍速"
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [6, 3],
"direction": "none",
"cost": 48
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [8, 3],
"direction": "none",
"cost": 49
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [7, 3],
"direction": "none",
"cost": 50
}
],
"retry_times": 9
},
{
"stage_name": "墓地旁",
"strategies": [
{
"tool_men": {
"vanguard": 1
},
"location": [3, 4],
"direction": "Right"
},
{
"tool_men": {
"vanguard": 1
},
"location": [2, 4],
"direction": "Right"
},
{
"tool_men": {
"caster": 1
},
"location": [2, 3],
"direction": "Right"
},
{
"tool_men": {
"supporter": 1
},
"location": [3, 5],
"direction": "Up"
},
{
"tool_men": {
"caster": 1
},
"location": [2, 5],
"direction": "Right"
},
{
"core": "天工夜行套装",
"tool_men": {},
"location": [1, 3],
"direction": "none"
},
{
"tool_men": {
"defender": 1
},
"location": [2, 4],
"direction": "Right"
},
{
"tool_men": {
"supporter": 1
},
"location": [3, 5],
"direction": "Up"
},
{
"core": "维什戴尔",
"tool_men": {
"special": 2
},
"location": [2, 3],
"direction": "Right"
},
{
"core": "阿斯卡纶",
"tool_men": {
"special": 2
},
"location": [3, 4],
"direction": "Up"
},
{
"core": "Mon3tr",
"tool_men": {
"special": 2
},
"location": [2, 5],
"direction": "Up"
},
{
"core": "重构体",
"tool_men": {},
"location": [1, 4],
"direction": "none"
},
{
"tool_men": {
"supporter": 99
},
"location": [3, 5],
"direction": "Up"
},
{
"tool_men": {
"caster": 99
},
"location": [3, 5],
"direction": "Up"
},
{
"core": "丛林用示踪信标",
"tool_men": {
"defender": 99
},
"location": [2, 4],
"direction": "Right"
}
],
"draw_as_possible": true,
"actions": [
{
"type": "二倍速"
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [3, 1],
"direction": "none",
"cost": 48
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [4, 1],
"direction": "none",
"cost": 49
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [5, 1],
"direction": "none",
"cost": 50
}
],
"retry_times": 9
},
{
"stage_name": "舞台上",
"strategies": [
{
"tool_men": {
"vanguard": 1
},
"location": [3, 4],
"direction": "Up"
},
{
"tool_men": {
"vanguard": 1
},
"location": [3, 5],
"direction": "Up"
},
{
"tool_men": {
"caster": 1
},
"location": [4, 4],
"direction": "Up"
},
{
"tool_men": {
"supporter": 1
},
"location": [6, 4],
"direction": "Up"
},
{
"tool_men": {
"caster": 1
},
"location": [4, 5],
"direction": "Up"
},
{
"core": "夜行钩爪模块",
"tool_men": {},
"location": [1, 5],
"direction": "none"
},
{
"tool_men": {
"defender": 1
},
"location": [3, 4],
"direction": "Up"
},
{
"tool_men": {
"supporter": 1
},
"location": [6, 4],
"direction": "Up"
},
{
"core": "阿斯卡纶",
"tool_men": {
"special": 2
},
"location": [4, 4],
"direction": "Up"
},
{
"core": "维什戴尔",
"tool_men": {
"special": 2
},
"location": [4, 5],
"direction": "Up"
},
{
"tool_men": {
"caster": 1
},
"location": [2, 4],
"direction": "Right"
},
{
"core": "Mon3tr",
"tool_men": {
"special": 2
},
"location": [2, 4],
"direction": "Right"
},
{
"core": "重构体",
"tool_men": {},
"location": [1, 3],
"direction": "none"
},
{
"tool_men": {
"supporter": 99
},
"location": [6, 4],
"direction": "Up"
},
{
"tool_men": {
"vanguard": 99
},
"location": [3, 5],
"direction": "Up"
},
{
"tool_men": {
"caster": 1
},
"location": [6, 4],
"direction": "Up"
},
{
"tool_men": {
"special": 99,
"caster": 99
},
"location": [6, 4],
"direction": "Up"
},
{
"core": "丛林用示踪信标",
"tool_men": {
"defender": 99
},
"location": [3, 4],
"direction": "Up"
}
],
"draw_as_possible": true,
"actions": [
{
"type": "二倍速"
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [3, 1],
"direction": "none",
"cost": 48
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [4, 1],
"direction": "none",
"cost": 49
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [5, 1],
"direction": "none",
"cost": 50
}
],
"retry_times": 9
},
{
"stage_name": "城门下",
"strategies": [
{
"tool_men": {
"vanguard": 1
},
"location": [6, 5],
"direction": "Up"
},
{
"tool_men": {
"vanguard": 1
},
"location": [5, 4],
"direction": "Right"
},
{
"tool_men": {
"caster": 1
},
"location": [7, 3],
"direction": "Left"
},
{
"tool_men": {
"supporter": 1
},
"location": [7, 4],
"direction": "Left"
},
{
"tool_men": {
"defender": 1
},
"location": [6, 5],
"direction": "Up"
},
{
"core": "夜行钩爪模块",
"tool_men": {},
"location": [4, 4],
"direction": "none"
},
{
"tool_men": {
"caster": 1
},
"location": [5, 6],
"direction": "Up"
},
{
"tool_men": {
"supporter": 1
},
"location": [6, 6],
"direction": "Up"
},
{
"core": "维什戴尔",
"tool_men": {
"special": 2
},
"location": [7, 3],
"direction": "Left"
},
{
"core": "阿斯卡纶",
"tool_men": {
"special": 2
},
"location": [5, 4],
"direction": "Up"
},
{
"core": "Mon3tr",
"tool_men": {
"special": 2
},
"location": [5, 6],
"direction": "Up"
},
{
"core": "重构体",
"tool_men": {},
"location": [4, 4],
"direction": "none"
},
{
"tool_men": {
"caster": 1
},
"location": [7, 4],
"direction": "Left"
},
{
"tool_men": {
"special": 1
},
"location": [7, 4],
"direction": "Left"
},
{
"tool_men": {
"caster": 1
},
"location": [7, 4],
"direction": "Left"
},
{
"tool_men": {
"supporter": 99
},
"location": [6, 6],
"direction": "Up"
},
{
"tool_men": {
"special": 99,
"caster": 99
},
"location": [6, 6],
"direction": "Up"
},
{
"core": "丛林用示踪信标",
"tool_men": {
"defender": 99
},
"location": [6, 5],
"direction": "Up"
}
],
"draw_as_possible": true,
"actions": [
{
"type": "二倍速"
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [5, 1],
"direction": "none",
"cost": 48
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [6, 1],
"direction": "none",
"cost": 49
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [7, 1],
"direction": "none",
"cost": 50
}
],
"retry_times": 9
},
{
"stage_name": "天地间",
"strategies": [
{
"tool_men": {
"vanguard": 1
},
"location": [3, 5],
"direction": "Right"
},
{
"tool_men": {
"vanguard": 1
},
"location": [2, 5],
"direction": "Right"
},
{
"tool_men": {
"caster": 1
},
"location": [4, 6],
"direction": "Up"
},
{
"tool_men": {
"supporter": 1
},
"location": [4, 4],
"direction": "Down"
},
{
"tool_men": {
"caster": 1
},
"location": [2, 6],
"direction": "Right"
},
{
"core": "夜行钩爪模块",
"tool_men": {},
"location": [1, 3],
"direction": "none"
},
{
"tool_men": {
"defender": 1
},
"location": [2, 5],
"direction": "Right"
},
{
"tool_men": {
"supporter": 1
},
"location": [4, 4],
"direction": "Down"
},
{
"core": "维什戴尔",
"tool_men": {
"special": 2
},
"location": [4, 6],
"direction": "Up"
},
{
"core": "阿斯卡纶",
"tool_men": {
"special": 2
},
"location": [3, 5],
"direction": "Right"
},
{
"core": "Mon3tr",
"tool_men": {
"special": 2
},
"location": [2, 6],
"direction": "Right"
},
{
"core": "重构体",
"tool_men": {},
"location": [4, 7],
"direction": "none"
},
{
"tool_men": {
"vanguard": 1
},
"location": [2, 4],
"direction": "Down"
},
{
"tool_men": {
"supporter": 99
},
"location": [2, 3],
"direction": "Down"
},
{
"tool_men": {
"special": 99
},
"location": [2, 4],
"direction": "Down"
},
{
"tool_men": {
"caster": 99
},
"location": [4, 4],
"direction": "Down"
},
{
"core": "丛林用示踪信标",
"tool_men": {
"defender": 99
},
"location": [2, 5],
"direction": "Right"
}
],
"draw_as_possible": true,
"actions": [
{
"type": "二倍速"
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [7, 4],
"direction": "none",
"cost": 48
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [8, 4],
"direction": "none",
"cost": 49
},
{
"type": "Deploy",
"name": "超重绝缘水泥",
"location": [9, 4],
"direction": "none",
"cost": 50
}
],
"retry_times": 9
}
]
}

View File

@@ -0,0 +1,34 @@
// <copyright file="CopilotFileItem.cs" company="MaaAssistantArknights">
// Part of the MaaWpfGui project, maintained by the MaaAssistantArknights team (Maa Team)
// Copyright (C) 2021-2025 MaaAssistantArknights Contributors
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License v3.0 only as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY
// </copyright>
#nullable enable
using System.Collections.ObjectModel;
namespace MaaWpfGui.Models;
/// <summary>
/// 文件项数据模型,用于 TreeView 显示
/// </summary>
public class CopilotFileItem
{
public string Name { get; set; } = string.Empty;
public string? FullPath { get; set; }
public string? RelativePath { get; set; }
public bool IsFolder { get; set; }
public ObservableCollection<CopilotFileItem> Children { get; set; } = [];
}

View File

@@ -14,5 +14,6 @@
<ResourceDictionary Source="Styles/DataGrid.xaml" />
<ResourceDictionary Source="Styles/PasswordBox.xaml" />
<ResourceDictionary Source="Styles/ToolTip.xaml" />
<ResourceDictionary Source="Styles/TreeView.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

View File

@@ -0,0 +1,57 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:hc="https://handyorg.github.io/handycontrol">
<!-- 文件树视图项样式 -->
<Style
x:Key="FileTreeViewItemStyle"
BasedOn="{StaticResource TreeViewItemBaseStyle}"
TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition MinHeight="{TemplateBinding MinHeight}" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border
Name="Bd"
Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{Binding Path=(hc:BorderElement.CornerRadius), RelativeSource={RelativeSource TemplatedParent}}"
SnapsToDevicePixels="true">
<DockPanel Margin="{Binding Converter={StaticResource TreeViewItemMarginConverter}, RelativeSource={RelativeSource TemplatedParent}}" LastChildFill="True">
<ToggleButton
Name="Expander"
ClickMode="Press"
IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
Style="{StaticResource ExpandCollapseToggleStyle}" />
<ContentPresenter
Name="PART_Header"
VerticalAlignment="Center"
ContentSource="Header"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</DockPanel>
</Border>
<ItemsPresenter Name="ItemsHost" Grid.Row="1" />
</Grid>
<ControlTemplate.Triggers>
<Trigger SourceName="Bd" Property="UIElement.IsMouseOver" Value="true">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource MouseOverRegionBrushOpacity75}" />
</Trigger>
<Trigger Property="TreeViewItem.IsSelected" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource MouseOverRegionBrushOpacity75}" />
</Trigger>
<Trigger Property="TreeViewItem.IsExpanded" Value="False">
<Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed" />
</Trigger>
<Trigger Property="ItemsControl.HasItems" Value="False">
<Setter TargetName="Expander" Property="Visibility" Value="Hidden" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@@ -59,6 +59,7 @@ public partial class CopilotViewModel : Screen
private readonly List<int> _copilotIdList = []; // 用于保存作业列表中的作业的Id对于同一个作业只有都执行成功才点赞
private readonly List<int> _recentlyRatedCopilotId = []; // TODO: 可能考虑加个持久化
private AsstTaskType _taskType = AsstTaskType.Copilot;
private readonly Dictionary<string, string> _copilotJsonPathMap = new(); // 下拉框与实际作业 json 档案路径对照表
/// <summary>
/// 缓存的已解析作业,非即时添加的作业会使用该缓存
@@ -79,6 +80,22 @@ public partial class CopilotViewModel : Screen
/// </summary>
public ObservableCollection<LogItemViewModel> LogItemViewModels { get; } = [];
/// <summary>
/// Gets the file items for TreeView.
/// </summary>
public ObservableCollection<CopilotFileItem> FileItems { get; } = [];
private bool _isFilePopupOpen;
/// <summary>
/// Gets or sets a value indicating whether gets or sets whether the file dropdown popup is open.
/// </summary>
public bool IsFilePopupOpen
{
get => _isFilePopupOpen;
set => SetAndNotify(ref _isFilePopupOpen, value);
}
/// <summary>
/// Gets or private sets the view models of Copilot items.
/// </summary>
@@ -239,6 +256,33 @@ public partial class CopilotViewModel : Screen
}
}
private string _displayFilename = string.Empty;
/// <summary>
/// Gets or sets the display filename (relative path).
/// </summary>
public string DisplayFilename
{
get => _displayFilename;
set
{
SetAndNotify(ref _displayFilename, value);
if (!string.IsNullOrEmpty(value))
{
var copilotRoot = Path.Combine(ResourceDir, "copilot");
var fullPath = Path.IsPathRooted(value) ? value : Path.Combine(copilotRoot, value);
if (File.Exists(fullPath))
{
Filename = fullPath;
}
else if (_copilotJsonPathMap.TryGetValue(Path.GetFileName(value), out var mappedPath))
{
Filename = mappedPath;
}
}
}
}
private string _filename = string.Empty;
/// <summary>
@@ -250,14 +294,45 @@ public partial class CopilotViewModel : Screen
set {
if (!File.Exists(value))
{
var resourceFile = Path.Combine(ResourceDir, "copilot", Path.GetFileName(value));
if (File.Exists(resourceFile))
// 从对照表取得完整 json 档案路径
if (_copilotJsonPathMap.TryGetValue(value, out var fullPath))
{
value = resourceFile;
value = fullPath;
}
else
{
var resourceFile = Path.Combine(ResourceDir, "copilot", Path.GetFileName(value));
if (File.Exists(resourceFile))
{
value = resourceFile;
}
}
}
SetAndNotify(ref _filename, value);
// 更新显示文件名(相对路径)
if (!string.IsNullOrEmpty(value))
{
var copilotRoot = Path.Combine(ResourceDir, "copilot");
if (value.StartsWith(copilotRoot, StringComparison.OrdinalIgnoreCase))
{
var relativePath = Path.GetRelativePath(copilotRoot, value);
_displayFilename = relativePath;
NotifyOfPropertyChange(nameof(DisplayFilename));
}
else
{
_displayFilename = value;
NotifyOfPropertyChange(nameof(DisplayFilename));
}
}
else
{
_displayFilename = string.Empty;
NotifyOfPropertyChange(nameof(DisplayFilename));
}
ClearLog();
if (string.IsNullOrWhiteSpace(value))
{
@@ -1301,28 +1376,150 @@ public partial class CopilotViewModel : Screen
}
/// <summary>
/// On comboBox drop down opened.
/// Load file items for TreeView.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The event arguments.</param>
[UsedImplicitly]
public void OnDropDownOpened(object sender, EventArgs e)
public void LoadFileItems()
{
if (sender is not ComboBox comboBox)
try
{
_copilotJsonPathMap.Clear();
FileItems.Clear();
var copilotRoot = Path.Combine(ResourceDir, "copilot");
// 获取根目录下的所有目录和文件
var directories = Directory.GetDirectories(copilotRoot);
var rootFiles = Directory.GetFiles(copilotRoot, "*.json");
// 添加根目录下的文件
foreach (var file in rootFiles)
{
var fileName = Path.GetFileName(file);
var relativePath = Path.GetRelativePath(copilotRoot, file);
_copilotJsonPathMap[fileName] = file;
FileItems.Add(new CopilotFileItem
{
Name = fileName,
FullPath = file,
RelativePath = relativePath,
IsFolder = false,
});
}
// 添加根目录下的文件夹支持嵌套old 文件夹放在最后)
var oldFolderItem = (CopilotFileItem?)null;
foreach (var dir in directories)
{
var dirName = Path.GetFileName(dir);
var folderItem = LoadFolderItem(dir, copilotRoot);
if (folderItem != null)
{
if (dirName.Equals("old", StringComparison.OrdinalIgnoreCase))
{
oldFolderItem = folderItem;
}
else
{
FileItems.Add(folderItem);
}
}
}
// 将 old 文件夹添加到最后
if (oldFolderItem != null)
{
FileItems.Add(oldFolderItem);
}
}
catch (Exception exception)
{
FileItems.Clear();
AddLog(exception.Message, UiLogColor.Error, showTime: false);
}
}
/// <summary>
/// 递归加载文件夹项(支持嵌套子文件夹)
/// </summary>
/// <param name="dirPath">文件夹路径</param>
/// <param name="copilotRoot">copilot 根目录路径</param>
/// <returns>文件项,如果文件夹为空则返回 null</returns>
private CopilotFileItem? LoadFolderItem(string dirPath, string copilotRoot)
{
var dirName = Path.GetFileName(dirPath);
var folderItem = new CopilotFileItem
{
Name = dirName,
IsFolder = true,
};
// 获取文件夹下的所有文件
var folderFiles = Directory.GetFiles(dirPath, "*.json");
foreach (var file in folderFiles)
{
var fileName = Path.GetFileName(file);
var relativePath = Path.GetRelativePath(copilotRoot, file);
_copilotJsonPathMap[fileName] = file;
folderItem.Children.Add(new CopilotFileItem
{
Name = fileName,
FullPath = file,
RelativePath = relativePath,
IsFolder = false,
});
}
// 获取文件夹下的所有子文件夹(递归加载)
var subDirectories = Directory.GetDirectories(dirPath);
foreach (var subDir in subDirectories)
{
var subFolderItem = LoadFolderItem(subDir, copilotRoot);
if (subFolderItem != null)
{
folderItem.Children.Add(subFolderItem);
}
}
// 如果文件夹为空(既没有文件也没有子文件夹),返回 null
if (folderItem.Children.Count == 0)
{
return null;
}
return folderItem;
}
/// <summary>
/// Handle file selection from TreeView.
/// </summary>
/// <param name="fileItem">The selected file item.</param>
[UsedImplicitly]
public void OnFileSelected(CopilotFileItem? fileItem)
{
if (fileItem == null || fileItem.IsFolder || string.IsNullOrEmpty(fileItem.FullPath))
{
return;
}
try
Filename = fileItem.FullPath;
IsFilePopupOpen = false;
}
/// <summary>
/// Toggle file popup.
/// </summary>
[UsedImplicitly]
public void ToggleFilePopup()
{
if (!IsFilePopupOpen)
{
var files = Directory.GetFiles(Path.Combine(ResourceDir, "copilot"), "*.json");
comboBox.ItemsSource = files.Select(Path.GetFileName).ToList();
}
catch (Exception exception)
{
comboBox.ItemsSource = null;
AddLog(exception.Message, UiLogColor.Error, showTime: false);
LoadFileItems();
}
IsFilePopupOpen = !IsFilePopupOpen;
}
private async Task AddCopilotTaskToList(string? stageName, bool isRaid)

View File

@@ -65,7 +65,7 @@
<TabControl.ItemContainerStyle>
<Style BasedOn="{StaticResource TabItemSliding}" TargetType="{x:Type TabItem}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="true">
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{DynamicResource RegionBrush}" />
</Trigger>
</Style.Triggers>
@@ -83,15 +83,81 @@
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ComboBox
Grid.Column="0"
Height="30"
hc:BorderElement.CornerRadius="4,0,0,4"
hc:InfoElement.Placeholder="{DynamicResource CopilotLocation}"
DropDownOpened="{s:Action OnDropDownOpened}"
IsEditable="True"
IsReadOnly="{c:Binding Path=!Idle}"
Text="{Binding Filename}" />
<Grid Grid.Column="0">
<TextBox
x:Name="FileTextBox"
Height="30"
hc:BorderElement.CornerRadius="4,0,0,4"
hc:InfoElement.Placeholder="{DynamicResource CopilotLocation}"
IsEnabled="{Binding Idle}"
Text="{Binding DisplayFilename, UpdateSourceTrigger=PropertyChanged}" />
<Button
Height="28"
Margin="1"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Background="{DynamicResource RegionBrushOpacity50}"
BorderThickness="0"
Click="{s:Action ToggleFilePopup}"
Cursor="Hand"
IsEnabled="{Binding Idle}">
<StackPanel>
<Path
Width="12"
Height="12"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="{StaticResource DownGeometry}"
Fill="{DynamicResource PrimaryTextBrush}"
Stretch="Uniform"
Visibility="{c:Binding !IsFilePopupOpen}" />
<Path
Width="12"
Height="12"
HorizontalAlignment="Center"
VerticalAlignment="Center"
d:Visibility="Collapsed"
Data="{StaticResource UpGeometry}"
Fill="{DynamicResource PrimaryTextBrush}"
Stretch="Uniform"
Visibility="{c:Binding IsFilePopupOpen}" />
</StackPanel>
</Button>
<Popup
MinWidth="{c:Binding 'ActualWidth + 90',
ElementName=FileTextBox}"
IsOpen="{Binding IsFilePopupOpen}"
Placement="Bottom"
PlacementTarget="{Binding ElementName=FileTextBox}"
StaysOpen="True">
<Border
MinWidth="{c:Binding 'ActualWidth + 90',
ElementName=FileTextBox}"
Background="{DynamicResource RegionBrush}"
BorderBrush="{DynamicResource BorderBrush}"
BorderThickness="1"
CornerRadius="4">
<TreeView
x:Name="FileTreeView"
Background="Transparent"
BorderThickness="0"
ItemsSource="{Binding FileItems}"
SelectedItemChanged="FileTreeView_SelectedItemChanged">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<controls:TextBlock
Margin="5"
HorizontalAlignment="Left"
Text="{Binding Name}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
<TreeView.ItemContainerStyle>
<Style BasedOn="{StaticResource FileTreeViewItemStyle}" TargetType="{x:Type TreeViewItem}" />
</TreeView.ItemContainerStyle>
</TreeView>
</Border>
</Popup>
</Grid>
<Button
Grid.Column="1"
Height="30"

View File

@@ -0,0 +1,37 @@
// <copyright file="CopilotView.xaml.cs" company="MaaAssistantArknights">
// Part of the MaaWpfGui project, maintained by the MaaAssistantArknights team (Maa Team)
// Copyright (C) 2021-2025 MaaAssistantArknights Contributors
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License v3.0 only as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY
// </copyright>
using System.Windows;
using MaaWpfGui.Models;
using MaaWpfGui.ViewModels.UI;
namespace MaaWpfGui.Views.UI;
/// <summary>
/// Interaction logic for CopilotView.xaml
/// </summary>
public partial class CopilotView
{
public CopilotView()
{
InitializeComponent();
}
private void FileTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
if (DataContext is CopilotViewModel viewModel && e.NewValue is CopilotFileItem fileItem && !fileItem.IsFolder)
{
viewModel.OnFileSelected(fileItem);
}
}
}