feat: 斗魂竞技场(CHERRY 多小队)适配 + bump 1.8.0#57
Merged
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
该 PR 将对局会话模型从传统的 teamOne/teamTwo 二元结构升级为统一的 subteams 多小队结构,以支持斗魂竞技场(CHERRY,8 队 × 2 人)在对局页、详情页、战绩列表和 AI 分析中的完整展示,并同步版本号至 1.8.0。
Changes:
- 会话数据契约重构:前后端统一为
subteams(CLASSIC 退化为 2 个 subteam;CHERRY 为多 subteam)。 - CHERRY 分组能力接入:详情页/战绩列表按
playerSubteamId/subteamPlacement展示小队与名次;对局页新增SubteamCard网格展示。 - 后端新增 EOG stats 客户端并调整事件流:
session-player-update-team-{one,two}合并为session-player-update(带subteamId)。
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| lol-record-analysis-tauri/src/views/Gaming.vue | 对局页改为按 subteams 渲染网格,并根据是否多小队切换紧凑布局 |
| lol-record-analysis-tauri/src/types/domain/match.ts | ParticipantStats 增加 CHERRY 小队/名次字段 |
| lol-record-analysis-tauri/src/types/domain/gaming.ts | SessionData 重构为 subteams 统一模型 |
| lol-record-analysis-tauri/src/services/ai/prompts/team.ts | AI team prompt 改为按 subteams 动态构造;player prompt 拆分 |
| lol-record-analysis-tauri/src/services/ai/prompts/team-player.ts | 新增单玩家分析 prompt 文件 |
| lol-record-analysis-tauri/src/composables/useSessionTiers.ts | 段位展示改为 subteamId -> TierDisplay[] |
| lol-record-analysis-tauri/src/composables/useSessionSync.ts | 前端 session 同步逻辑适配 subteams + 合并后的 player-update 事件 |
| lol-record-analysis-tauri/src/composables/useMatchDetailPlayers.ts | CHERRY 模式下按 playerSubteamId 分组并按名次排序展示 |
| lol-record-analysis-tauri/src/composables/useMatchDetailPlayers.spec.ts | 新增 CHERRY 分组测试用例 |
| lol-record-analysis-tauri/src/components/record/RecordCard.vue | CHERRY 战绩卡片右上角展示“第 X 名” |
| lol-record-analysis-tauri/src/components/record/MatchDetailModal.vue | 详情页布局微调(防止 shrink) |
| lol-record-analysis-tauri/src/components/gaming/SubteamCard.vue | 新增小队卡片组件,内部渲染 PlayerCard + 占位 |
| lol-record-analysis-tauri/src/components/gaming/PlayerHistoryGrid.vue | 样式微调避免换行/压缩 |
| lol-record-analysis-tauri/src/components/gaming/PlayerCard.vue | 增加 density 变体与 mine/enemy 边框样式 |
| lol-record-analysis-tauri/src-tauri/tauri.conf.json | 版本号 bump 到 1.8.0 |
| lol-record-analysis-tauri/src-tauri/src/lcu/api/session.rs | Queue/OnePlayer 补充 gameMode/teamParticipantId 字段 |
| lol-record-analysis-tauri/src-tauri/src/lcu/api/model.rs | Stats 补充 CHERRY subteam 字段并添加反序列化测试 |
| lol-record-analysis-tauri/src-tauri/src/lcu/api/eog_stats.rs | 新增 EOG stats block 客户端用于 CHERRY 权威分组 |
| lol-record-analysis-tauri/src-tauri/src/lcu/api.rs | 导出 eog_stats 模块 |
| lol-record-analysis-tauri/src-tauri/src/command/session.rs | 后端 session 主流程重构为 CLASSIC/CHERRY 分支 + 新事件流 |
| lol-record-analysis-tauri/src-tauri/examples/probe_arena.rs | 新增探针示例用于落盘斗魂相关 schema |
| docs/superpowers/specs/2026-05-10-arena-multiteam-support-design.md | 新增设计文档说明多小队适配方案 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+495
to
+520
| // 我方组优先;其它按 key 升序 | ||
| let mut groups: Vec<Vec<crate::lcu::api::session::OnePlayer>> = grouped.into_values().collect(); | ||
| groups.sort_by_key(|g| !g.iter().any(|p| p.puuid == *my_puuid)); | ||
|
|
||
| // 删除 Tag 标记(减少数据量) | ||
| delete_meet_gamers_record(&mut session_data); | ||
| let to_summoner = |p: &crate::lcu::api::session::OnePlayer| SessionSummoner { | ||
| champion_id: p.champion_id, | ||
| champion_key: format!("champion_{}", p.champion_id), | ||
| summoner: Summoner { | ||
| puuid: p.puuid.clone(), | ||
| ..Default::default() | ||
| }, | ||
| ..Default::default() | ||
| }; | ||
|
|
||
| // 发送完成事件 | ||
| app_handle | ||
| .emit("session-complete", &session_data) | ||
| .map_err(|e| e.to_string())?; | ||
| let mut subteams: Vec<Subteam> = Vec::with_capacity(groups.len()); | ||
| let mut my_subteam_id = 0; | ||
| for (i, group) in groups.iter().enumerate() { | ||
| let subteam_id = (i as i32) + 1; | ||
| if group.iter().any(|p| p.puuid == *my_puuid) { | ||
| my_subteam_id = subteam_id; | ||
| } | ||
| subteams.push(Subteam { | ||
| subteam_id, | ||
| players: group.iter().map(to_summoner).collect(), | ||
| }); | ||
| } |
Comment on lines
236
to
250
| if phase == "ChampSelect" { | ||
| match get_champion_select_session().await { | ||
| Ok(select_session) => { | ||
| // 转换类型:从 champion_select::OnePlayer 到 session::OnePlayer | ||
| session.game_data.team_one = select_session | ||
| .my_team | ||
| .into_iter() | ||
| .map(|p| crate::lcu::api::session::OnePlayer { | ||
| champion_id: p.champion_id, | ||
| puuid: p.puuid, | ||
| selected_position: String::new(), | ||
| team_participant_id: 0, | ||
| }) | ||
| .collect(); | ||
| session.game_data.team_two.clear(); // 选英雄阶段看不到对手 | ||
| session.game_data.team_two.clear(); | ||
| } |
Comment on lines
+27
to
+32
| <script setup lang="ts"> | ||
| import { computed } from 'vue' | ||
| import { NTag } from 'naive-ui' | ||
| import PlayerCard from './PlayerCard.vue' | ||
| import type { Subteam } from '@renderer/types/domain/gaming' | ||
| import type { TierDisplay } from '@renderer/composables/useSessionTiers' |
| * 对局会话领域模型:当前 session / 我方与敌方 | ||
| * 对局会话领域模型:subteams 统一模型 | ||
| * - CLASSIC 模式:subteams.length === 2,[0] 是我方,[1] 是敌方 | ||
| * - CHERRY 模式:subteams.length 为 1~8(按 teamParticipantId 临时分组) |
34234dc to
ae2b7c1
Compare
The spec documents the data contract changes and design for斗魂竞技场 (CHERRY mode) support. The probe binary at src-tauri/examples/probe_arena.rs reuses existing LCU auth to dump session/match-detail/champ-select JSON to .claude/plans/arena-probe/, useful for re-verifying schema when LCU contract changes.
让对局页 / 详情页 / 战绩列表 / AI 分析全套支持斗魂竞技场(CHERRY 模式,
8 小队 × 2 人)。数据模型从 team_one / team_two 二元字段统一到
subteams: Vec<Subteam>,5v5 是其特例(length=2)。
后端
- Stats 加 playerSubteamId / subteamPlacement 字段
- SessionData 重构成 { gameMode, isMultiTeam, mySubteamId, subteams }
- process_session_data 走 CLASSIC / CHERRY 分支
- 新增 lol-end-of-game/v1/gameclient-eog-stats-block 客户端,InProgress
阶段拉 16 人 puuid → subteamId(1-8) 权威映射;champ-select 等 EOG 不
可用时回退到 lobby 的 teamParticipantId 分组
- 事件流 session-player-update-team-{one,two} 合并为 session-player-update
+ subteamId payload
- add_pre_group_markers / insert_meet_gamers_record 等改成遍历 subteams
前端
- 新增 SubteamCard 组件 + PlayerCard density: 'normal'|'compact' 变体
- Gaming.vue 用 grid:CLASSIC 两列、CHERRY 两列 × 自动行 + 整页可滚
- useMatchDetailPlayers 在 CHERRY 时按 playerSubteamId 分组,标题显示
'队伍 N · 第 X 名';非 CHERRY 走原 teamId 分组
- RecordCard CHERRY 局右上角显示 '第 X 名'
- AI prompt buildTeamAnalysisPrompt 按 subteams 数组动态构造,CHERRY
和 CLASSIC 两种模板分支;buildPlayerAnalysisPrompt 拆到 team-player.ts
测试
- Rust:5 个 session 单测覆盖 CLASSIC swap / CHERRY 8 小队 / 残局 / 稀疏
tpid 不强行配对
- TS:useMatchDetailPlayers.spec.ts 验证 CHERRY 按 subteamId 分组、按
placement 升序,CLASSIC 仍按 win/loss 排序
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
team_one/team_two二元字段统一到subteams: Vec<Subteam>,5v5 是其特例(length=2)lol-end-of-game/v1/gameclient-eog-stats-block拉权威 1~8 小队号——避开 lobby 阶段稀疏teamParticipantId的坑关键改动
后端
Stats加playerSubteamId/subteamPlacement字段SessionData重构成{ gameMode, isMultiTeam, mySubteamId, subteams }process_session_data走 CLASSIC / CHERRY 分支eog_stats.rs客户端,拉 16 名玩家的 puuid → subteamId 映射session-player-update-team-{one,two}合并为session-player-update+subteamIdpayload前端
SubteamCard组件 +PlayerCarddensity: 'normal'|'compact'变体Gaming.vue用 grid:CLASSIC 两列,CHERRY 两列 × 自动行 + 整页可滚useMatchDetailPlayers在 CHERRY 时按playerSubteamId分组,标题显示"队伍 N · 第 X 名"RecordCardCHERRY 局右上角显示"第 X 名"buildTeamAnalysisPrompt按subteams数组动态构造Spec & 探针
docs/superpowers/specs/2026-05-10-arena-multiteam-support-design.mdsrc-tauri/examples/probe_arena.rs复用 LCU 鉴权直接落盘,schema 变化时可重跑Test plan
npm run check全绿(prettier + eslint + vue-tsc + cargo fmt + clippy -Dwarnings)npm run test217 前端测试通过(含新增useMatchDetailPlayers.spec.ts)cargo test --lib95 后端测试通过(含 5 个 session 单测:CLASSIC swap、CHERRY 分组、稀疏 tpid 保留)已知限制