From 6790ea41b2fbcfebe8ad2ea1d55b7a109f4dd212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E9=94=8B?= <2535831261@qq.com> Date: Tue, 28 Jul 2026 09:30:24 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BA=BA=E5=B7=A5=E5=A4=84?= =?UTF-8?q?=E7=90=86=E5=BC=B9=E7=AA=97=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/widget_manual_winner_dialog.dart | 277 ++++++++++++------ 1 file changed, 191 insertions(+), 86 deletions(-) diff --git a/lib/features/competition_teams/widgets/widget_manual_winner_dialog.dart b/lib/features/competition_teams/widgets/widget_manual_winner_dialog.dart index be2c4bd..8d88431 100644 --- a/lib/features/competition_teams/widgets/widget_manual_winner_dialog.dart +++ b/lib/features/competition_teams/widgets/widget_manual_winner_dialog.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:recording_tool/features/competition_teams/model/model_competition_team_detail.dart'; -import 'package:recording_tool/shared/widgets/app_button.dart'; +import 'package:recording_tool/gen/assets.gen.dart'; /// 弹窗回传选中侧索引:0 = teamA(红队),1 = teamB(蓝队) class ManualWinnerDialog extends StatefulWidget { @@ -62,84 +62,109 @@ class _ManualWinnerDialogState extends State { Widget build(BuildContext context) { final teamA = _teamA; final teamB = _teamB; + final maxHeight = MediaQuery.sizeOf(context).height * 0.78; - return AlertDialog( - insetPadding: EdgeInsets.symmetric(horizontal: 22.w), - contentPadding: EdgeInsets.zero, - clipBehavior: Clip.antiAlias, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(18.r)), - content: SizedBox( - width: 320.w, - child: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Image.asset( - 'assets/images/image_dialog_bg.png', - width: 320.w, - height: 112.h, - fit: BoxFit.cover, - ), - Padding( - padding: EdgeInsets.fromLTRB(20.w, 8.h, 20.w, 20.h), - child: Column( - children: [ - Text( - '请在比赛结束前处理', - key: const ValueKey('manual-winner-dialog-title'), - style: TextStyle( - fontSize: 20.sp, - fontWeight: FontWeight.w700, - color: const Color(0xFF20242B), + return Dialog( + insetPadding: EdgeInsets.symmetric(horizontal: 48.w), + backgroundColor: Colors.transparent, + elevation: 0, + child: ConstrainedBox( + constraints: BoxConstraints(maxWidth: 380.w, maxHeight: maxHeight), + child: Stack( + clipBehavior: Clip.none, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(16.r), + child: Material( + color: Colors.white, + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: EdgeInsets.fromLTRB(18.w, 18.h, 18.w, 18.h), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox(height: 26.h), + Text( + '请在比赛结束前处理', + key: const ValueKey('manual-winner-dialog-title'), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18.sp, + height: 1.3, + fontWeight: FontWeight.w700, + color: const Color(0xFF20242B), + fontFamily: 'PingFang SC', + ), + ), + SizedBox(height: 16.h), + if (teamA != null) ...[ + _TeamChoice( + team: teamA, + sideIndex: 0, + color: const Color(0xFFFF6575), + selected: _selectedSideIndex == 0, + onTap: () => + setState(() => _selectedSideIndex = 0), + ), + SizedBox(height: 10.h), + ], + if (teamB != null) + _TeamChoice( + team: teamB, + sideIndex: 1, + color: const Color(0xFF21C5AC), + selected: _selectedSideIndex == 1, + onTap: () => + setState(() => _selectedSideIndex = 1), + ), + SizedBox(height: 18.h), + Row( + children: [ + Expanded( + child: _DialogActionButton( + label: '取消', + onPressed: () => + Navigator.of(context).pop(), + ), + ), + SizedBox(width: 14.w), + Expanded( + child: _DialogActionButton( + label: '确定', + filled: true, + onPressed: _selectedSideIndex == null + ? null + : () => Navigator.of( + context, + ).pop(_selectedSideIndex), + ), + ), + ], + ), + ], + ), ), - ), - SizedBox(height: 16.h), - if (teamA != null) ...[ - _TeamChoice( - team: teamA, - sideIndex: 0, - color: const Color(0xFFFF6B75), - selected: _selectedSideIndex == 0, - onTap: () => setState(() => _selectedSideIndex = 0), - ), - 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: [ - Expanded( - child: AppButton( - label: '取消', - variant: AppButtonVariant.secondary, - onPressed: () => Navigator.of(context).pop(), - ), - ), - SizedBox(width: 14.w), - Expanded( - child: AppButton( - label: '确定', - onPressed: _selectedSideIndex == null - ? null - : () => Navigator.of( - context, - ).pop(_selectedSideIndex), - ), - ), - ], - ), - ], + ), ), ), - ], - ), + ), + Positioned( + top: -90.h, + left: 0, + right: 0, + child: Image.asset( + Assets.images.imageDialogBg.path, + width: double.infinity, + height: 112.h, + fit: BoxFit.cover, + alignment: Alignment.topCenter, + ), + ), + ], ), ), ); @@ -167,12 +192,15 @@ class _TeamChoice extends StatelessWidget { ? team.teamName! : '未命名队伍'; final players = team.playerNames; + final backgroundColor = selected + ? color.withValues(alpha: 0.13) + : color.withValues(alpha: 0.07); return Semantics( selected: selected, button: true, label: '选择$name直接获胜', child: Material( - color: color.withValues(alpha: selected ? 0.16 : 0.08), + color: backgroundColor, borderRadius: BorderRadius.circular(12.r), child: InkWell( key: ValueKey('winner-choice-side-$sideIndex'), @@ -180,12 +208,12 @@ class _TeamChoice extends StatelessWidget { borderRadius: BorderRadius.circular(12.r), child: Container( width: double.infinity, - padding: EdgeInsets.symmetric(horizontal: 14.w, vertical: 12.h), + padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 12.h), decoration: BoxDecoration( borderRadius: BorderRadius.circular(12.r), border: Border.all( - color: selected ? color : color.withValues(alpha: 0.35), - width: selected ? 2 : 1, + color: selected ? color : color.withValues(alpha: 0.32), + width: 1, ), ), child: Row( @@ -196,11 +224,23 @@ class _TeamChoice extends StatelessWidget { height: 22.r, decoration: BoxDecoration( shape: BoxShape.circle, - border: Border.all(color: selected ? color : Colors.grey), - color: selected ? color : Colors.transparent, + border: Border.all( + color: selected ? color : const Color(0xFFB0B4BB), + width: 1.2.r, + ), + color: Colors.transparent, ), child: selected - ? Icon(Icons.check, size: 15.r, color: Colors.white) + ? Center( + child: Container( + width: 10.r, + height: 10.r, + decoration: BoxDecoration( + color: color, + shape: BoxShape.circle, + ), + ), + ) : null, ), SizedBox(width: 12.w), @@ -210,19 +250,27 @@ class _TeamChoice extends StatelessWidget { children: [ Text( name, + maxLines: 1, + overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 17.sp, - fontWeight: FontWeight.w600, + height: 1.25, + fontWeight: FontWeight.w700, color: const Color(0xFF20242B), + fontFamily: 'PingFang SC', ), ), if (players.isNotEmpty) ...[ SizedBox(height: 4.h), Text( players, + maxLines: 1, + overflow: TextOverflow.ellipsis, style: TextStyle( - fontSize: 14.sp, - color: const Color(0xFF606874), + fontSize: 15.sp, + height: 1.25, + color: const Color(0xFF69717E), + fontFamily: 'PingFang SC', ), ), ], @@ -232,10 +280,12 @@ class _TeamChoice extends StatelessWidget { SizedBox(width: 8.w), Text( '直接获胜', + maxLines: 1, style: TextStyle( - fontSize: 13.sp, - fontWeight: FontWeight.w600, + fontSize: 15.sp, + fontWeight: FontWeight.w700, color: color, + fontFamily: 'PingFang SC', ), ), ], @@ -246,3 +296,58 @@ class _TeamChoice extends StatelessWidget { ); } } + +class _DialogActionButton extends StatelessWidget { + const _DialogActionButton({ + required this.label, + required this.onPressed, + this.filled = false, + }); + + final String label; + final VoidCallback? onPressed; + final bool filled; + + @override + Widget build(BuildContext context) { + final enabled = onPressed != null; + final radius = BorderRadius.circular(24.r); + final backgroundColor = filled + ? (enabled ? null : const Color(0xFFD2D3D8)) + : const Color(0xFFF1F1F1); + final gradient = filled && enabled + ? const LinearGradient(colors: [Color(0xFF2F8DFF), Color(0xFF58D1EE)]) + : null; + + return SizedBox( + height: 40.h, + child: DecoratedBox( + decoration: BoxDecoration( + color: backgroundColor, + gradient: gradient, + borderRadius: radius, + ), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: onPressed, + borderRadius: radius, + child: Center( + child: Text( + label, + style: TextStyle( + fontSize: 15.sp, + fontWeight: FontWeight.w500, + color: filled + ? (enabled ? Colors.white : const Color(0xFF8D9098)) + : const Color(0xFF343941), + fontFamily: 'PingFang SC', + ), + ), + ), + ), + ), + ), + ); + } +}