新增人工设置晋级/淘汰功能,更新相关数据模型和API接口;重构比赛页面以支持新逻辑,优化用户交互体验。
This commit is contained in:
@@ -1,21 +1,31 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:recording_tool/features/competition_teams/model/model_competition_team.dart';
|
||||
import 'package:recording_tool/features/competition_teams/model/model_competition_team_detail.dart';
|
||||
import 'package:recording_tool/shared/widgets/app_button.dart';
|
||||
|
||||
/// 弹窗回传选中侧索引:0 = teamA(红队),1 = teamB(蓝队)
|
||||
class ManualWinnerDialog extends StatefulWidget {
|
||||
const ManualWinnerDialog({super.key, required this.matchup});
|
||||
const ManualWinnerDialog({
|
||||
super.key,
|
||||
required this.matchup,
|
||||
this.initialWinnerSideIndex,
|
||||
});
|
||||
|
||||
final CompetitionMatchup matchup;
|
||||
final Matchup matchup;
|
||||
final int? initialWinnerSideIndex;
|
||||
|
||||
static Future<String?> show(
|
||||
static Future<int?> show(
|
||||
BuildContext context, {
|
||||
required CompetitionMatchup matchup,
|
||||
required Matchup matchup,
|
||||
int? initialWinnerSideIndex,
|
||||
}) {
|
||||
return showDialog<String>(
|
||||
return showDialog<int>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (_) => ManualWinnerDialog(matchup: matchup),
|
||||
builder: (_) => ManualWinnerDialog(
|
||||
matchup: matchup,
|
||||
initialWinnerSideIndex: initialWinnerSideIndex,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -24,16 +34,35 @@ class ManualWinnerDialog extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _ManualWinnerDialogState extends State<ManualWinnerDialog> {
|
||||
String? _selectedTeamId;
|
||||
/// 0 = teamA,1 = teamB
|
||||
int? _selectedSideIndex;
|
||||
|
||||
Team? get _teamA {
|
||||
final teams = widget.matchup.teamA;
|
||||
if (teams == null || teams.isEmpty) return null;
|
||||
return teams.first;
|
||||
}
|
||||
|
||||
Team? get _teamB {
|
||||
final teams = widget.matchup.teamB;
|
||||
if (teams == null || teams.isEmpty) return null;
|
||||
return teams.first;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_selectedTeamId = widget.matchup.winnerTeamId;
|
||||
final initial = widget.initialWinnerSideIndex;
|
||||
if (initial == 0 || initial == 1) {
|
||||
_selectedSideIndex = initial;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final teamA = _teamA;
|
||||
final teamB = _teamB;
|
||||
|
||||
return AlertDialog(
|
||||
insetPadding: EdgeInsets.symmetric(horizontal: 22.w),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
@@ -65,23 +94,24 @@ class _ManualWinnerDialogState extends State<ManualWinnerDialog> {
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
_TeamChoice(
|
||||
team: widget.matchup.teamA,
|
||||
color: const Color(0xFFFF6B75),
|
||||
selected: _selectedTeamId == widget.matchup.teamA.id,
|
||||
onTap: () => setState(
|
||||
() => _selectedTeamId = widget.matchup.teamA.id,
|
||||
if (teamA != null) ...[
|
||||
_TeamChoice(
|
||||
team: teamA,
|
||||
sideIndex: 0,
|
||||
color: const Color(0xFFFF6B75),
|
||||
selected: _selectedSideIndex == 0,
|
||||
onTap: () => setState(() => _selectedSideIndex = 0),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10.h),
|
||||
_TeamChoice(
|
||||
team: widget.matchup.teamB,
|
||||
color: const Color(0xFF20BFA9),
|
||||
selected: _selectedTeamId == widget.matchup.teamB.id,
|
||||
onTap: () => setState(
|
||||
() => _selectedTeamId = widget.matchup.teamB.id,
|
||||
SizedBox(height: 10.h),
|
||||
],
|
||||
if (teamB != null)
|
||||
_TeamChoice(
|
||||
team: teamB,
|
||||
sideIndex: 1,
|
||||
color: const Color(0xFF20BFA9),
|
||||
selected: _selectedSideIndex == 1,
|
||||
onTap: () => setState(() => _selectedSideIndex = 1),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20.h),
|
||||
Row(
|
||||
children: [
|
||||
@@ -96,11 +126,11 @@ class _ManualWinnerDialogState extends State<ManualWinnerDialog> {
|
||||
Expanded(
|
||||
child: AppButton(
|
||||
label: '确定',
|
||||
onPressed: _selectedTeamId == null
|
||||
onPressed: _selectedSideIndex == null
|
||||
? null
|
||||
: () => Navigator.of(
|
||||
context,
|
||||
).pop(_selectedTeamId),
|
||||
).pop(_selectedSideIndex),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -119,27 +149,33 @@ class _ManualWinnerDialogState extends State<ManualWinnerDialog> {
|
||||
class _TeamChoice extends StatelessWidget {
|
||||
const _TeamChoice({
|
||||
required this.team,
|
||||
required this.sideIndex,
|
||||
required this.color,
|
||||
required this.selected,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
final CompetitionTeam team;
|
||||
final Team team;
|
||||
final int sideIndex;
|
||||
final Color color;
|
||||
final bool selected;
|
||||
final VoidCallback onTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final name = team.teamName?.trim().isNotEmpty == true
|
||||
? team.teamName!
|
||||
: '未命名队伍';
|
||||
final players = team.playerNames;
|
||||
return Semantics(
|
||||
selected: selected,
|
||||
button: true,
|
||||
label: '选择${team.name}直接获胜',
|
||||
label: '选择$name直接获胜',
|
||||
child: Material(
|
||||
color: color.withValues(alpha: selected ? 0.16 : 0.08),
|
||||
borderRadius: BorderRadius.circular(12.r),
|
||||
child: InkWell(
|
||||
key: ValueKey('winner-choice-${team.id}'),
|
||||
key: ValueKey('winner-choice-side-$sideIndex'),
|
||||
onTap: onTap,
|
||||
borderRadius: BorderRadius.circular(12.r),
|
||||
child: Container(
|
||||
@@ -173,21 +209,23 @@ class _TeamChoice extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
team.name,
|
||||
name,
|
||||
style: TextStyle(
|
||||
fontSize: 17.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: const Color(0xFF20242B),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 4.h),
|
||||
Text(
|
||||
team.playerNames,
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
color: const Color(0xFF606874),
|
||||
if (players.isNotEmpty) ...[
|
||||
SizedBox(height: 4.h),
|
||||
Text(
|
||||
players,
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
color: const Color(0xFF606874),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user