3 Commits
Author SHA1 Message Date
linfeng 13ecb2fccc 优化赛事信息页 UI 2026-07-28 10:12:13 +08:00
linfeng e3f9c8ebc0 优化团队赛页面 UI 2026-07-28 10:00:02 +08:00
linfeng 6790ea41b2 优化人工处理弹窗 UI 2026-07-28 09:30:24 +08:00
5 changed files with 259 additions and 135 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 833 KiB

@@ -275,12 +275,12 @@ class _EventTeamMatchPageState extends ConsumerState<EventTeamMatchPage> {
top: false, top: false,
child: Column( child: Column(
children: [ children: [
SizedBox(height: 10.h), // SizedBox(height: 10.h),
_MatchMetadata(detail: _detail), _MatchMetadata(detail: _detail),
SizedBox(height: 12.h), // SizedBox(height: 12.h),
Expanded( Expanded(
child: SingleChildScrollView( child: SingleChildScrollView(
padding: EdgeInsets.fromLTRB(8.w, 0, 8.w, 20.h), padding: EdgeInsets.symmetric(horizontal: 0.w, vertical: 20.h),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@@ -288,7 +288,7 @@ class _EventTeamMatchPageState extends ConsumerState<EventTeamMatchPage> {
sideLabel: '红方', sideLabel: '红方',
team: redTeam, team: redTeam,
members: _redMembers, members: _redMembers,
backgroundImage: 'assets/images/image_red_team.png', backgroundImage: Assets.images.imageRedTeam.path,
accentColor: const Color(0xFFE84B5B), accentColor: const Color(0xFFE84B5B),
verifiedUserIds: _verifiedUserIds, verifiedUserIds: _verifiedUserIds,
winner: _winnerSideIndex == 0, winner: _winnerSideIndex == 0,
@@ -298,7 +298,7 @@ class _EventTeamMatchPageState extends ConsumerState<EventTeamMatchPage> {
sideLabel: '蓝方', sideLabel: '蓝方',
team: blueTeam, team: blueTeam,
members: _blueMembers, members: _blueMembers,
backgroundImage: 'assets/images/image_blue_team.png', backgroundImage: Assets.images.imageBlueTeam.path,
accentColor: const Color(0xFF287FDD), accentColor: const Color(0xFF287FDD),
verifiedUserIds: _verifiedUserIds, verifiedUserIds: _verifiedUserIds,
winner: _winnerSideIndex == 1, winner: _winnerSideIndex == 1,
@@ -451,6 +451,7 @@ class _TeamCard extends StatelessWidget {
image: AssetImage(backgroundImage), image: AssetImage(backgroundImage),
fit: BoxFit.fill, fit: BoxFit.fill,
), ),
color: Colors.white,
), ),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -460,7 +461,7 @@ class _TeamCard extends StatelessWidget {
children: [ children: [
Expanded( Expanded(
child: Text( child: Text(
'$sideLabel队伍名称${team.name}', '$sideLabel队伍名称${team.name}队伍',
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(
@@ -509,16 +510,56 @@ class _TeamCard extends StatelessWidget {
_TeamTextLine( _TeamTextLine(
label: '队长', label: '队长',
text: _formatMember(leader), text: _formatMember(leader),
showOk: leaderVerified || leader.isLeader, showOk: verifiedUserIds.contains(leader.userId),
), ),
if (players.isNotEmpty) if (players.isNotEmpty)
_TeamTextLine( Row(
label: '选手', children: [
text: players.map(_formatMember).join(''), Text(
showOk: players.any( '选手:',
(member) => verifiedUserIds.contains(member.userId), style: TextStyle(
fontSize: 13.sp,
height: 1.35,
color: const Color(0xFF747B86),
fontWeight: FontWeight.w500,
fontFamily: 'PingFang SC',
), ),
), ),
...players.map(
(member) => Row(
children: [
Text(
_formatMember(member),
style: TextStyle(
fontSize: 13.sp,
height: 1.35,
color: const Color(0xFF4D545F),
),
),
if (verifiedUserIds.contains(member.userId))
Padding(
padding: EdgeInsets.only(left: 6.w),
child: Image.asset(
Assets.images.imageOk.path,
width: 18.w,
height: 14.h,
fit: BoxFit.contain,
),
),
Text(
(member != players.last ? '' : ''),
style: TextStyle(
fontSize: 13.sp,
height: 1.35,
color: const Color(0xFF4D545F),
),
),
],
),
),
],
),
], ],
], ],
), ),
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.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/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(蓝队) /// 弹窗回传选中侧索引:0 = teamA(红队),1 = teamB(蓝队)
class ManualWinnerDialog extends StatefulWidget { class ManualWinnerDialog extends StatefulWidget {
@@ -62,35 +62,41 @@ class _ManualWinnerDialogState extends State<ManualWinnerDialog> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final teamA = _teamA; final teamA = _teamA;
final teamB = _teamB; final teamB = _teamB;
final maxHeight = MediaQuery.sizeOf(context).height * 0.78;
return AlertDialog( return Dialog(
insetPadding: EdgeInsets.symmetric(horizontal: 22.w), insetPadding: EdgeInsets.symmetric(horizontal: 48.w),
contentPadding: EdgeInsets.zero, backgroundColor: Colors.transparent,
clipBehavior: Clip.antiAlias, elevation: 0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(18.r)), child: ConstrainedBox(
content: SizedBox( constraints: BoxConstraints(maxWidth: 380.w, maxHeight: maxHeight),
width: 320.w, child: Stack(
clipBehavior: Clip.none,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(16.r),
child: Material(
color: Colors.white,
child: SingleChildScrollView( child: SingleChildScrollView(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Image.asset(
'assets/images/image_dialog_bg.png',
width: 320.w,
height: 112.h,
fit: BoxFit.cover,
),
Padding( Padding(
padding: EdgeInsets.fromLTRB(20.w, 8.h, 20.w, 20.h), padding: EdgeInsets.fromLTRB(18.w, 18.h, 18.w, 18.h),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min,
children: [ children: [
SizedBox(height: 26.h),
Text( Text(
'请在比赛结束前处理', '请在比赛结束前处理',
key: const ValueKey('manual-winner-dialog-title'), key: const ValueKey('manual-winner-dialog-title'),
textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: 20.sp, fontSize: 18.sp,
height: 1.3,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
color: const Color(0xFF20242B), color: const Color(0xFF20242B),
fontFamily: 'PingFang SC',
), ),
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
@@ -98,9 +104,10 @@ class _ManualWinnerDialogState extends State<ManualWinnerDialog> {
_TeamChoice( _TeamChoice(
team: teamA, team: teamA,
sideIndex: 0, sideIndex: 0,
color: const Color(0xFFFF6B75), color: const Color(0xFFFF6575),
selected: _selectedSideIndex == 0, selected: _selectedSideIndex == 0,
onTap: () => setState(() => _selectedSideIndex = 0), onTap: () =>
setState(() => _selectedSideIndex = 0),
), ),
SizedBox(height: 10.h), SizedBox(height: 10.h),
], ],
@@ -108,24 +115,26 @@ class _ManualWinnerDialogState extends State<ManualWinnerDialog> {
_TeamChoice( _TeamChoice(
team: teamB, team: teamB,
sideIndex: 1, sideIndex: 1,
color: const Color(0xFF20BFA9), color: const Color(0xFF21C5AC),
selected: _selectedSideIndex == 1, selected: _selectedSideIndex == 1,
onTap: () => setState(() => _selectedSideIndex = 1), onTap: () =>
setState(() => _selectedSideIndex = 1),
), ),
SizedBox(height: 20.h), SizedBox(height: 18.h),
Row( Row(
children: [ children: [
Expanded( Expanded(
child: AppButton( child: _DialogActionButton(
label: '取消', label: '取消',
variant: AppButtonVariant.secondary, onPressed: () =>
onPressed: () => Navigator.of(context).pop(), Navigator.of(context).pop(),
), ),
), ),
SizedBox(width: 14.w), SizedBox(width: 14.w),
Expanded( Expanded(
child: AppButton( child: _DialogActionButton(
label: '确定', label: '确定',
filled: true,
onPressed: _selectedSideIndex == null onPressed: _selectedSideIndex == null
? null ? null
: () => Navigator.of( : () => Navigator.of(
@@ -142,6 +151,22 @@ class _ManualWinnerDialogState extends State<ManualWinnerDialog> {
), ),
), ),
), ),
),
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! ? team.teamName!
: '未命名队伍'; : '未命名队伍';
final players = team.playerNames; final players = team.playerNames;
final backgroundColor = selected
? color.withValues(alpha: 0.13)
: color.withValues(alpha: 0.07);
return Semantics( return Semantics(
selected: selected, selected: selected,
button: true, button: true,
label: '选择$name直接获胜', label: '选择$name直接获胜',
child: Material( child: Material(
color: color.withValues(alpha: selected ? 0.16 : 0.08), color: backgroundColor,
borderRadius: BorderRadius.circular(12.r), borderRadius: BorderRadius.circular(12.r),
child: InkWell( child: InkWell(
key: ValueKey('winner-choice-side-$sideIndex'), key: ValueKey('winner-choice-side-$sideIndex'),
@@ -180,12 +208,12 @@ class _TeamChoice extends StatelessWidget {
borderRadius: BorderRadius.circular(12.r), borderRadius: BorderRadius.circular(12.r),
child: Container( child: Container(
width: double.infinity, width: double.infinity,
padding: EdgeInsets.symmetric(horizontal: 14.w, vertical: 12.h), padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 12.h),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.r), borderRadius: BorderRadius.circular(12.r),
border: Border.all( border: Border.all(
color: selected ? color : color.withValues(alpha: 0.35), color: selected ? color : color.withValues(alpha: 0.32),
width: selected ? 2 : 1, width: 1,
), ),
), ),
child: Row( child: Row(
@@ -196,11 +224,23 @@ class _TeamChoice extends StatelessWidget {
height: 22.r, height: 22.r,
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
border: Border.all(color: selected ? color : Colors.grey), border: Border.all(
color: selected ? color : Colors.transparent, color: selected ? color : const Color(0xFFB0B4BB),
width: 1.2.r,
),
color: Colors.transparent,
), ),
child: selected 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, : null,
), ),
SizedBox(width: 12.w), SizedBox(width: 12.w),
@@ -210,19 +250,27 @@ class _TeamChoice extends StatelessWidget {
children: [ children: [
Text( Text(
name, name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(
fontSize: 17.sp, fontSize: 17.sp,
fontWeight: FontWeight.w600, height: 1.25,
fontWeight: FontWeight.w700,
color: const Color(0xFF20242B), color: const Color(0xFF20242B),
fontFamily: 'PingFang SC',
), ),
), ),
if (players.isNotEmpty) ...[ if (players.isNotEmpty) ...[
SizedBox(height: 4.h), SizedBox(height: 4.h),
Text( Text(
players, players,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 15.sp,
color: const Color(0xFF606874), height: 1.25,
color: const Color(0xFF69717E),
fontFamily: 'PingFang SC',
), ),
), ),
], ],
@@ -232,10 +280,12 @@ class _TeamChoice extends StatelessWidget {
SizedBox(width: 8.w), SizedBox(width: 8.w),
Text( Text(
'直接获胜', '直接获胜',
maxLines: 1,
style: TextStyle( style: TextStyle(
fontSize: 13.sp, fontSize: 15.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w700,
color: color, 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',
),
),
),
),
),
),
);
}
}
+7 -34
View File
@@ -10,6 +10,7 @@ import 'package:recording_tool/features/competition_teams/server/server_competit
import 'package:recording_tool/features/events/model/model_event_info.dart'; import 'package:recording_tool/features/events/model/model_event_info.dart';
import 'package:recording_tool/features/events/state/state_event_info.dart'; import 'package:recording_tool/features/events/state/state_event_info.dart';
import 'package:recording_tool/features/events/view_model/view_model_event_info.dart'; import 'package:recording_tool/features/events/view_model/view_model_event_info.dart';
import 'package:recording_tool/gen/assets.gen.dart';
import 'package:recording_tool/shared/widgets/app_webview.dart'; import 'package:recording_tool/shared/widgets/app_webview.dart';
import 'package:recording_tool/shared/widgets/widgets.dart'; import 'package:recording_tool/shared/widgets/widgets.dart';
@@ -117,21 +118,14 @@ class _TopGradientHeader extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SizedBox( return Positioned(
top: -10.h,
left: 0,
right: 0,
child: SizedBox(
height: 219.h, height: 219.h,
width: double.infinity, width: double.infinity,
child: DecoratedBox( child: Image.asset(Assets.images.imageEventInfoBarBg.path),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(36.r),
bottomRight: Radius.circular(36.r),
),
gradient: const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Color(0xFF5EC9FF), Color(0xFF178BFF)],
),
),
), ),
); );
} }
@@ -194,27 +188,6 @@ class _ProfileSection extends StatelessWidget {
), ),
child: Stack( child: Stack(
children: [ children: [
// Positioned(
// top: -28.h,
// right: -14.w,
// child: Transform.rotate(
// angle: 0.68,
// child: Container(
// width: 110.w,
// height: 138.h,
// decoration: BoxDecoration(
// gradient: LinearGradient(
// begin: Alignment.topCenter,
// end: Alignment.bottomCenter,
// colors: [
// const Color(0xFF53D7FF).withValues(alpha: 0.12),
// const Color(0xFFFF85C8).withValues(alpha: 0.13),
// ],
// ),
// ),
// ),
// ),
// ),
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
+5
View File
@@ -44,6 +44,10 @@ class $AssetsImagesGen {
AssetGenImage get imageDialogBg => AssetGenImage get imageDialogBg =>
const AssetGenImage('assets/images/image_dialog_bg.png'); const AssetGenImage('assets/images/image_dialog_bg.png');
/// File path: assets/images/image_event_info_bar_bg.png
AssetGenImage get imageEventInfoBarBg =>
const AssetGenImage('assets/images/image_event_info_bar_bg.png');
/// File path: assets/images/image_logo.png /// File path: assets/images/image_logo.png
AssetGenImage get imageLogo => AssetGenImage get imageLogo =>
const AssetGenImage('assets/images/image_logo.png'); const AssetGenImage('assets/images/image_logo.png');
@@ -83,6 +87,7 @@ class $AssetsImagesGen {
imageAppNameText, imageAppNameText,
imageBlueTeam, imageBlueTeam,
imageDialogBg, imageDialogBg,
imageEventInfoBarBg,
imageLogo, imageLogo,
imageOk, imageOk,
imagePageBg, imagePageBg,